[PATCH 0/5] MR10806: wineandroid: switch ioctl handling to socket-based transport (part of !10569)
Part of !10569. This series converts wineandroid ioctl handling to a socket-based transport integrated with the Android main thread looper. It introduces reply_fd plumbing across all ioctl handlers, switches dispatch to a UNIX SEQPACKET socket, and migrates all ioctls to the new transport. The legacy unixlib/ntoskrnl ioctl path is removed as part of this transition. The final commit simplifies error handling by returning ioctl errors directly, matching the expectations of the socket-based transport and removing the need for additional conversion layers. Overall, this prepares the driver for further changes by unifying ioctl handling around a single transport and execution model. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Add an optional reply_fd parameter to all android ioctl handlers and propagate it through android_dispatch_ioctl and android_ioctl, including all ioctl call sites. This prepares the ioctl path for passing file descriptors alongside regular responses. The new parameter is not used yet and all callers pass NULL, so there is no change in behavior. This change is intentionally kept separate since it is mechanically large but conceptually simple, making subsequent functional changes easier to review. This is a preparatory change with no functional impact. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 55 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index d78913af830..5aa8c1055ac 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -566,7 +566,7 @@ static void create_desktop_view( JNIEnv* env ) unwrap_java_call(); } -static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; @@ -588,7 +588,7 @@ static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWOR return STATUS_SUCCESS; } -static NTSTATUS destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; @@ -610,7 +610,7 @@ static NTSTATUS destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO return STATUS_SUCCESS; } -static NTSTATUS windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; @@ -634,7 +634,7 @@ static NTSTATUS windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, return STATUS_SUCCESS; } -static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ANativeWindow *parent; struct ioctl_android_dequeueBuffer *res = data; @@ -733,7 +733,7 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO return STATUS_SUCCESS; } -static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_cancelBuffer *res = data; struct ANativeWindow *parent; @@ -756,7 +756,7 @@ static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWOR return android_error_to_status( ret ); } -static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_queueBuffer *res = data; struct ANativeWindow *parent; @@ -779,7 +779,7 @@ static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD return android_error_to_status( ret ); } -static NTSTATUS query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_query *res = data; struct ANativeWindow *parent; @@ -799,7 +799,7 @@ static NTSTATUS query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_s return android_error_to_status( ret ); } -static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_perform *res = data; struct ANativeWindow *parent; @@ -886,7 +886,7 @@ static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out return android_error_to_status( ret ); } -static NTSTATUS setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_set_swap_interval *res = data; struct ANativeWindow *parent; @@ -905,7 +905,7 @@ static NTSTATUS setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, D return android_error_to_status( ret ); } -static NTSTATUS setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; @@ -926,7 +926,7 @@ static NTSTATUS setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, D return STATUS_SUCCESS; } -static NTSTATUS setCapture_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS setCapture_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_set_capture *res = data; @@ -940,7 +940,7 @@ static NTSTATUS setCapture_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD return STATUS_SUCCESS; } -static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; @@ -978,7 +978,7 @@ static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD o return STATUS_SUCCESS; } -typedef NTSTATUS (*ioctl_func)( JNIEnv* env, void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ); +typedef NTSTATUS (*ioctl_func)( JNIEnv* env, void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ); static const ioctl_func ioctl_funcs[] = { createWindow_ioctl, /* IOCTL_CREATE_WINDOW */ @@ -1009,11 +1009,12 @@ NTSTATUS android_dispatch_ioctl( void *arg ) if (in_size >= sizeof(*header)) { + int reply_fd = -1; irp->IoStatus.Information = 0; pthread_mutex_lock(&dispatch_ioctl_lock); irp->IoStatus.Status = func( jni_env, irp->AssociatedIrp.SystemBuffer, in_size, irpsp->Parameters.DeviceIoControl.OutputBufferLength, - &irp->IoStatus.Information ); + &irp->IoStatus.Information, &reply_fd ); pthread_mutex_unlock(&dispatch_ioctl_lock); } else irp->IoStatus.Status = STATUS_INVALID_PARAMETER; @@ -1059,7 +1060,7 @@ void start_android_device(void) /* Client-side ioctl support */ -static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size ) +static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *reply_fd ) { static const WCHAR deviceW[] = { '\\','D','e','v','i','c','e','\\','W','i','n','e','A','n','d','r','o','i','d', 0 }; static HANDLE device; @@ -1119,7 +1120,7 @@ static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuff res.buffer_id = -1; res.generation = 0; - ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size ); + ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size, NULL ); if (ret) return ret; if (size < sizeof(res)) return -EINVAL; @@ -1175,7 +1176,7 @@ static int cancelBuffer( struct ANativeWindow *window, struct ANativeWindowBuffe cancel.hdr.hwnd = HandleToLong( win->hwnd ); cancel.hdr.opengl = win->opengl; wait_fence_and_close( fence ); - return android_ioctl( IOCTL_CANCEL_BUFFER, &cancel, sizeof(cancel), NULL, NULL ); + return android_ioctl( IOCTL_CANCEL_BUFFER, &cancel, sizeof(cancel), NULL, NULL, NULL ); } static int queueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer *buffer, int fence ) @@ -1194,7 +1195,7 @@ static int queueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer queue.hdr.hwnd = HandleToLong( win->hwnd ); queue.hdr.opengl = win->opengl; wait_fence_and_close( fence ); - return android_ioctl( IOCTL_QUEUE_BUFFER, &queue, sizeof(queue), NULL, NULL ); + return android_ioctl( IOCTL_QUEUE_BUFFER, &queue, sizeof(queue), NULL, NULL, NULL ); } static int dequeueBuffer_DEPRECATED( struct ANativeWindow *window, struct ANativeWindowBuffer **buffer ) @@ -1229,7 +1230,7 @@ static int setSwapInterval( struct ANativeWindow *window, int interval ) swap.hdr.hwnd = HandleToLong( win->hwnd ); swap.hdr.opengl = win->opengl; swap.interval = interval; - return android_ioctl( IOCTL_SET_SWAP_INT, &swap, sizeof(swap), NULL, NULL ); + return android_ioctl( IOCTL_SET_SWAP_INT, &swap, sizeof(swap), NULL, NULL, NULL ); } static int query( const ANativeWindow *window, int what, int *value ) @@ -1242,7 +1243,7 @@ static int query( const ANativeWindow *window, int what, int *value ) query.hdr.hwnd = HandleToLong( win->hwnd ); query.hdr.opengl = win->opengl; query.what = what; - ret = android_ioctl( IOCTL_QUERY, &query, sizeof(query), &query, &size ); + ret = android_ioctl( IOCTL_QUERY, &query, sizeof(query), &query, &size, NULL ); TRACE( "hwnd %p what %d got %d -> %p\n", win->hwnd, what, query.value, value ); if (!ret) *value = query.value; return ret; @@ -1384,7 +1385,7 @@ static int perform( ANativeWindow *window, int operation, ... ) break; } va_end( args ); - return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL ); + return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL, NULL ); } struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl ) @@ -1417,7 +1418,7 @@ struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl ) req.hdr.opengl = win->opengl; req.parent = get_ioctl_win_parent( NtUserGetAncestor( hwnd, GA_PARENT )); req.is_desktop = hwnd == desktop_window; - android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL ); + android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL, NULL ); return &win->win; } @@ -1450,7 +1451,7 @@ void destroy_ioctl_window( HWND hwnd, BOOL opengl ) req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.opengl = opengl; - android_ioctl( IOCTL_DESTROY_WINDOW, &req, sizeof(req), NULL, NULL ); + android_ioctl( IOCTL_DESTROY_WINDOW, &req, sizeof(req), NULL, NULL, NULL ); } int ioctl_window_pos_changed( HWND hwnd, const struct window_rects *rects, @@ -1467,7 +1468,7 @@ int ioctl_window_pos_changed( HWND hwnd, const struct window_rects *rects, req.flags = flags; req.after = HandleToLong( after ); req.owner = HandleToLong( owner ); - return android_ioctl( IOCTL_WINDOW_POS_CHANGED, &req, sizeof(req), NULL, NULL ); + return android_ioctl( IOCTL_WINDOW_POS_CHANGED, &req, sizeof(req), NULL, NULL, NULL ); } int ioctl_set_window_parent( HWND hwnd, HWND parent ) @@ -1477,7 +1478,7 @@ int ioctl_set_window_parent( HWND hwnd, HWND parent ) req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.opengl = FALSE; req.parent = get_ioctl_win_parent( parent ); - return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL ); + return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL, NULL ); } int ioctl_set_capture( HWND hwnd ) @@ -1486,7 +1487,7 @@ int ioctl_set_capture( HWND hwnd ) req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.opengl = FALSE; - return android_ioctl( IOCTL_SET_CAPTURE, &req, sizeof(req), NULL, NULL ); + return android_ioctl( IOCTL_SET_CAPTURE, &req, sizeof(req), NULL, NULL, NULL ); } int ioctl_set_cursor( int id, int width, int height, @@ -1505,7 +1506,7 @@ int ioctl_set_cursor( int id, int width, int height, req->hotspotx = hotspotx; req->hotspoty = hotspoty; memcpy( req->bits, bits, width * height * sizeof(req->bits[0]) ); - ret = android_ioctl( IOCTL_SET_CURSOR, req, size, NULL, NULL ); + ret = android_ioctl( IOCTL_SET_CURSOR, req, size, NULL, NULL, NULL ); free( req ); return ret; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Implement ioctl handling over a UNIX SEQPACKET socket integrated with the Android main thread ALooper. Ioctls are now dispatched directly from ALooper callbacks using a JNI-attached environment captured during looper initialization, removing the need for a dedicated dispatch thread. A temporary bootstrap thread is used to obtain the main thread looper without interfering with the current Wine/JVM execution context. Keep dequeueBuffer on the old transport for bisect safety, as it still depends on wine_server_fd_to_handle() and requires a Wine TEB. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/WineActivity.java | 35 ++- dlls/wineandroid.drv/android.h | 7 + dlls/wineandroid.drv/device.c | 301 +++++++++++++++++++++---- dlls/wineandroid.drv/init.c | 11 + 4 files changed, 302 insertions(+), 52 deletions(-) diff --git a/dlls/wineandroid.drv/WineActivity.java b/dlls/wineandroid.drv/WineActivity.java index 6488188b93a..1ee99b8a037 100644 --- a/dlls/wineandroid.drv/WineActivity.java +++ b/dlls/wineandroid.drv/WineActivity.java @@ -30,6 +30,8 @@ import android.graphics.SurfaceTexture; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.preference.PreferenceManager; import android.system.ErrnoException; import android.util.Log; @@ -52,6 +54,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.concurrent.CountDownLatch; import static android.system.Os.setenv; import static android.system.Os.getenv; @@ -59,6 +62,7 @@ public class WineActivity extends Activity { private native String wine_init( String[] cmdline ); + private native void wine_looper_init(); public native void wine_desktop_changed( int width, int height ); public native void wine_config_changed( int dpi ); public native void wine_surface_changed( int hwnd, Surface surface, boolean opengl ); @@ -73,6 +77,8 @@ public class WineActivity extends Activity protected WineWindow message_window; private PointerIcon current_cursor; + private static final Handler uiHandler = new Handler(Looper.getMainLooper()); + @Override public void onCreate(Bundle savedInstanceState) { @@ -834,31 +840,40 @@ public void window_pos_changed( int hwnd, int flags, int insert_after, int owner win.pos_changed( flags, insert_after, owner, style, window_rect, client_rect, visible_rect ); } + /* Always post to the UI thread handler instead of using runOnUiThread(). + * runOnUiThread() may execute the runnable immediately if already on the + * UI thread, which can break assumptions about ordering and lead to crashes. + * We need deferred execution to preserve the original asynchronous behavior. + */ + private void postToUiThread(Runnable r) { + uiHandler.post(r); + } + public void createDesktopView() { - runOnUiThread( new Runnable() { public void run() { create_desktop_view(); }} ); + postToUiThread( new Runnable() { public void run() { create_desktop_view(); }} ); } public void createWindow( final int hwnd, final boolean is_desktop, final boolean opengl, final int parent ) { - runOnUiThread( new Runnable() { public void run() { create_window( hwnd, is_desktop, opengl, parent ); }} ); + postToUiThread( new Runnable() { public void run() { create_window( hwnd, is_desktop, opengl, parent ); }} ); } public void destroyWindow( final int hwnd ) { - runOnUiThread( new Runnable() { public void run() { destroy_window( hwnd ); }} ); + postToUiThread( new Runnable() { public void run() { destroy_window( hwnd ); }} ); } public void setParent( final int hwnd, final int parent ) { - runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent ); }} ); + postToUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent ); }} ); } public void setCursor( final int id, final int width, final int height, final int hotspotx, final int hotspoty, final int bits[] ) { if (Build.VERSION.SDK_INT < 24) return; - runOnUiThread( new Runnable() { public void run() { set_cursor( id, width, height, hotspotx, hotspoty, bits ); }} ); + postToUiThread( new Runnable() { public void run() { set_cursor( id, width, height, hotspotx, hotspoty, bits ); }} ); } public void windowPosChanged( final int hwnd, final int flags, final int insert_after, @@ -873,8 +888,16 @@ public void windowPosChanged( final int hwnd, final int flags, final int insert_ final Rect window_rect = new Rect( window_left, window_top, window_right, window_bottom ); final Rect client_rect = new Rect( client_left, client_top, client_right, client_bottom ); final Rect visible_rect = new Rect( visible_left, visible_top, visible_right, visible_bottom ); - runOnUiThread( new Runnable() { + postToUiThread( new Runnable() { public void run() { window_pos_changed( hwnd, flags, insert_after, owner, style, window_rect, client_rect, visible_rect ); }} ); } + + private void obtainLooper() { + CountDownLatch latch = new CountDownLatch(1); + runOnUiThread( new Runnable() { public void run() { + try { wine_looper_init(); } finally { latch.countDown(); } + }}); + try { latch.await(); } catch ( Exception e ) {} + } } diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index f30cf849c41..4882ca91f8b 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -28,6 +28,7 @@ #include <jni.h> #include <android/log.h> #include <android/input.h> +#include <android/looper.h> #include <android/native_window_jni.h> #include "windef.h" @@ -58,6 +59,11 @@ DECL_FUNCPTR( AHardwareBuffer_unlock ); DECL_FUNCPTR( AHardwareBuffer_recvHandleFromUnixSocket ); DECL_FUNCPTR( AHardwareBuffer_sendHandleToUnixSocket ); DECL_FUNCPTR( ANativeWindowBuffer_getHardwareBuffer ); +DECL_FUNCPTR( ALooper_acquire ); +DECL_FUNCPTR( ALooper_forThread ); +DECL_FUNCPTR( ALooper_addFd ); +DECL_FUNCPTR( ALooper_removeFd ); +DECL_FUNCPTR( ALooper_release ); #endif #undef DECL_FUNCPTR @@ -137,6 +143,7 @@ extern void set_screen_dpi( DWORD dpi ); extern void update_keyboard_lock_state( WORD vkey, UINT state ); /* JNI entry points */ +extern void looper_init( JNIEnv *env, jobject obj ); extern void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ); extern void config_changed( JNIEnv *env, jobject obj, jint dpi ); extern void surface_changed( JNIEnv *env, jobject obj, jint win, jobject surface, diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 5aa8c1055ac..c57d5ea1bc6 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -32,6 +32,8 @@ #include <stdarg.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> #include <unistd.h> #include "ntstatus.h" @@ -134,6 +136,14 @@ struct native_win_wrapper LONG ref; }; +#define IPC_SOCKET_NAME "\0\\Device\\WineAndroid" +#define IPC_SOCKET_ADDR_LEN ((socklen_t)(offsetof(struct sockaddr_un, sun_path) + sizeof(IPC_SOCKET_NAME) - 1)) + +static const struct sockaddr_un ipc_addr = { + .sun_family = AF_UNIX, + .sun_path = IPC_SOCKET_NAME, +}; + struct ioctl_header { int hwnd; @@ -541,10 +551,8 @@ static jobject load_java_method( JNIEnv* env, jmethodID *method, const char *nam { jclass class; - wrap_java_call(); class = (*env)->GetObjectClass( env, java_object ); *method = (*env)->GetMethodID( env, class, name, args ); - unwrap_java_call(); if (!*method) { LOG( FIXME, "method %s not found\n", name ); @@ -559,10 +567,11 @@ static void create_desktop_view( JNIEnv* env ) static jmethodID method; jobject object; - if (!(object = load_java_method( env, &method, "createDesktopView", "()V" ))) return; - wrap_java_call(); + if (!(object = load_java_method( env, &method, "createDesktopView", "()V" ))) goto end; + (*env)->CallVoidMethod( env, object, method ); +end: unwrap_java_call(); } @@ -582,9 +591,7 @@ static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWOR if (!(object = load_java_method( env, &method, "createWindow", "(IZZI)V" ))) return STATUS_NOT_SUPPORTED; - wrap_java_call(); (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->is_desktop, res->hdr.opengl, res->parent ); - unwrap_java_call(); return STATUS_SUCCESS; } @@ -603,9 +610,7 @@ static NTSTATUS destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO if (!(object = load_java_method( env, &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED; - wrap_java_call(); (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd ); - unwrap_java_call(); if (win_data) free_native_win_data( win_data ); return STATUS_SUCCESS; } @@ -625,12 +630,10 @@ static NTSTATUS windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, if (!(object = load_java_method( env, &method, "windowPosChanged", "(IIIIIIIIIIIIIIIII)V" ))) return STATUS_NOT_SUPPORTED; - wrap_java_call(); (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->flags, res->after, res->owner, res->style, res->window_rect.left, res->window_rect.top, res->window_rect.right, res->window_rect.bottom, res->client_rect.left, res->client_rect.top, res->client_rect.right, res->client_rect.bottom, res->visible_rect.left, res->visible_rect.top, res->visible_rect.right, res->visible_rect.bottom ); - unwrap_java_call(); return STATUS_SUCCESS; } @@ -750,9 +753,7 @@ static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWOR if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return STATUS_INVALID_HANDLE; LOG( TRACE, "%08x buffer %p\n", res->hdr.hwnd, buffer ); - wrap_java_call(); ret = parent->cancelBuffer( parent, buffer, -1 ); - unwrap_java_call(); return android_error_to_status( ret ); } @@ -773,9 +774,7 @@ static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return STATUS_INVALID_HANDLE; LOG( TRACE, "%08x buffer %p\n", res->hdr.hwnd, buffer ); - wrap_java_call(); ret = parent->queueBuffer( parent, buffer, -1 ); - unwrap_java_call(); return android_error_to_status( ret ); } @@ -793,9 +792,7 @@ static NTSTATUS query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_s if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; *ret_size = sizeof( *res ); - wrap_java_call(); ret = parent->query( parent, res->what, &res->value ); - unwrap_java_call(); return android_error_to_status( ret ); } @@ -814,57 +811,39 @@ static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out switch (res->operation) { case NATIVE_WINDOW_SET_BUFFERS_FORMAT: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0] ); - unwrap_java_call(); if (!ret) win_data->buffer_format = res->args[0]; break; case NATIVE_WINDOW_API_CONNECT: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0] ); - unwrap_java_call(); if (!ret) win_data->api = res->args[0]; break; case NATIVE_WINDOW_API_DISCONNECT: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0] ); - unwrap_java_call(); if (!ret) win_data->api = 0; break; case NATIVE_WINDOW_SET_USAGE: case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: case NATIVE_WINDOW_SET_SCALING_MODE: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0] ); - unwrap_java_call(); break; case NATIVE_WINDOW_SET_BUFFER_COUNT: - wrap_java_call(); ret = parent->perform( parent, res->operation, (size_t)res->args[0] ); - unwrap_java_call(); break; case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0], res->args[1] ); - unwrap_java_call(); break; case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0], res->args[1], res->args[2] ); - unwrap_java_call(); break; case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: - wrap_java_call(); ret = parent->perform( parent, res->operation, res->args[0] | ((int64_t)res->args[1] << 32) ); - unwrap_java_call(); break; case NATIVE_WINDOW_CONNECT: case NATIVE_WINDOW_DISCONNECT: case NATIVE_WINDOW_UNLOCK_AND_POST: - wrap_java_call(); ret = parent->perform( parent, res->operation ); - unwrap_java_call(); break; case NATIVE_WINDOW_SET_CROP: { @@ -873,9 +852,7 @@ static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out rect.top = res->args[1]; rect.right = res->args[2]; rect.bottom = res->args[3]; - wrap_java_call(); ret = parent->perform( parent, res->operation, &rect ); - unwrap_java_call(); break; } case NATIVE_WINDOW_LOCK: @@ -899,9 +876,7 @@ static NTSTATUS setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, D win_data->swap_interval = res->interval; if (!(parent = win_data->parent)) return STATUS_SUCCESS; - wrap_java_call(); ret = parent->setSwapInterval( parent, res->interval ); - unwrap_java_call(); return android_error_to_status( ret ); } @@ -920,9 +895,7 @@ static NTSTATUS setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, D if (!(object = load_java_method( env, &method, "setParent", "(II)V" ))) return STATUS_NOT_SUPPORTED; - wrap_java_call(); (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->parent ); - unwrap_java_call(); return STATUS_SUCCESS; } @@ -961,8 +934,6 @@ static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD o if (!(object = load_java_method( env, &method, "setCursor", "(IIIII[I)V" ))) return STATUS_NOT_SUPPORTED; - wrap_java_call(); - if (size) { jintArray array = (*env)->NewIntArray( env, size ); @@ -973,8 +944,6 @@ static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD o } else (*env)->CallVoidMethod( env, object, method, res->id, 0, 0, 0, 0, NULL ); - unwrap_java_call(); - return STATUS_SUCCESS; } @@ -1046,21 +1015,201 @@ NTSTATUS android_java_uninit( void *arg ) return STATUS_SUCCESS; } +static ALooper *looper; +static JNIEnv *looper_env; /* JNIEnv for the main thread looper. Must only be used from that thread. */ + +void looper_init( JNIEnv* env, jobject obj ) +{ + looper_env = env; + if (!(looper = pALooper_forThread())) + { + LOG( ERR, "No looper for current thread\n" ); + abort(); + } + pALooper_acquire( looper ); +} + +/* Handle a single ioctl request from a client socket. + * Returns 0 if a request was handled successfully and the caller may + * continue draining the socket, -1 if there is nothing more to read + * for now, and 1 if the client fd should be closed. + */ +static int handle_ioctl_message( JNIEnv *env, int fd ) +{ + char buffer[1024], control[CMSG_SPACE(sizeof(int))]; + int code = 0, status = -EINVAL, reply_fd = -1; + ULONG_PTR reply_size = 0; + ssize_t ret; + struct iovec iov[2] = { { &code, sizeof(code) }, { buffer, sizeof(buffer) } }; + struct iovec reply_iov[2] = { { &status, sizeof(status) }, { buffer, 0 } }; + struct msghdr msg = { NULL, 0, iov, 2, NULL, 0, 0 }; + struct msghdr reply = { NULL, 0, reply_iov, 2, NULL, 0, 0 }; + struct cmsghdr *cmsg; + + ret = recvmsg( fd, &msg, MSG_DONTWAIT ); + if (ret < 0) + { + if (errno == EINTR) return 0; + if (errno == EAGAIN || errno == EWOULDBLOCK) return -1; + return 1; + } + + if (!ret || ret < sizeof(code)) return 1; + ret -= sizeof(code); + + if ((unsigned int)code < NB_IOCTLS) + { + if (ret >= sizeof(struct ioctl_header)) + { + pthread_mutex_lock( &dispatch_ioctl_lock ); + status = status_to_android_error( + ioctl_funcs[code]( env, buffer, ret, sizeof(buffer), &reply_size, &reply_fd ) ); + pthread_mutex_unlock( &dispatch_ioctl_lock ); + } + } + else + { + LOG( FIXME, "ioctl %x not supported\n", code ); + status = -ENOTSUP; + } + + reply_iov[1].iov_len = reply_size; + if (reply_fd != -1) + { + reply.msg_control = control; + reply.msg_controllen = sizeof(control); + cmsg = CMSG_FIRSTHDR( &reply ); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN( sizeof(reply_fd) ); + memcpy( CMSG_DATA(cmsg), &reply_fd, sizeof(reply_fd) ); + reply.msg_controllen = cmsg->cmsg_len; + } + + ret = sendmsg( fd, &reply, 0 ); + if (reply_fd != -1) close( reply_fd ); + return ret < 0 ? 1 : 0; +} + +static int looper_handle_client( int fd, int events, void *data ) +{ + for (;;) + { + int ret = (events & (ALOOPER_EVENT_HANGUP | ALOOPER_EVENT_ERROR)) ? 1 : handle_ioctl_message( looper_env, fd ); + + if (!ret) continue; + + if (ret > 0) + { + pALooper_removeFd( looper, fd ); + close( fd ); + } + break; + } + + return 1; +} + +static int looper_handle_listen( int fd, int events, void *data ) +{ + for (;;) + { + int client = accept4( fd, NULL, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK ); + + if (client < 0) + { + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == EWOULDBLOCK) break; + LOG( ERR, "accept4 failed: %s\n", strerror( errno ) ); + break; + } + + if (pALooper_addFd( looper, client, client, ALOOPER_EVENT_INPUT | ALOOPER_EVENT_HANGUP | ALOOPER_EVENT_ERROR, looper_handle_client, NULL ) != 1) { + LOG( ERR, "Failed to add client to ALooper\n" ); + close( client ); + } + } + + return 1; +} + +static void *bootstrap_looper_thread( void *arg ) +{ + JNIEnv *env; + jmethodID method = NULL; + jobject object = NULL; + int sockfd; + + if (!java_vm || (*java_vm)->AttachCurrentThread( java_vm, &env, 0 ) != JNI_OK) + { + LOG( ERR, "Failed to attach current thread\n" ); + return NULL; + } + + if (!(object = load_java_method( env, &method, "obtainLooper", "()V" ))) + { + LOG( ERR, "Failed to obtain looper\n" ); + abort(); + } + (*env)->CallVoidMethod( env, object, method ); + + sockfd = socket( AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0 ); + if (sockfd < 0) + { + LOG( ERR, "Failed to open server socket: %s\n", strerror( errno ) ); + abort(); + } + + if (bind( sockfd, (const struct sockaddr *)&ipc_addr, IPC_SOCKET_ADDR_LEN ) < 0 || + listen( sockfd, 32 ) < 0) + { + LOG( ERR, "Failed to bind server socket: %s\n", strerror( errno ) ); + close(sockfd); + abort(); + } + + if (pALooper_addFd( looper, sockfd, sockfd, ALOOPER_EVENT_INPUT, looper_handle_listen, NULL ) != 1) { + LOG( ERR, "Failed to add listening socket to main looper\n" ); + close(sockfd); + abort(); + } + + (*java_vm)->DetachCurrentThread( java_vm ); + return NULL; +} + void start_android_device(void) { void *ret_ptr; ULONG ret_len; struct dispatch_callback_params params = {.callback = start_device_callback}; + pthread_t t; + log_flags = __wine_dbg_get_channel_flags(&__wine_dbch_android); + + /* Use a temporary bootstrap thread to request the main thread looper + * without interfering with the current Wine/JVM execution context + * (including register and thread-state assumptions). Actual ioctl + * dispatch then runs from the main thread looper. + */ + if (!pthread_create( &t, NULL, bootstrap_looper_thread, NULL )) + pthread_join(t, NULL); + else + { + LOG( ERR, "Failed to spawn looper bootstrap thread\n" ); + abort(); + } + if (KeUserDispatchCallback( ¶ms, sizeof(params), &ret_ptr, &ret_len )) return; if (ret_len == sizeof(thread)) thread = *(HANDLE *)ret_ptr; + return; } /* Client-side ioctl support */ -static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *reply_fd ) +static int android_ioctl_old( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *reply_fd ) { static const WCHAR deviceW[] = { '\\','D','e','v','i','c','e','\\','W','i','n','e','A','n','d','r','o','i','d', 0 }; static HANDLE device; @@ -1094,6 +1243,66 @@ static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void return status_to_android_error( status ); } +static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *recv_fd ) +{ + static int device_fd = -1; + static pthread_mutex_t device_mutex = PTHREAD_MUTEX_INITIALIZER; + int status, err = -ENOENT; + ssize_t ret; + char control[CMSG_SPACE(sizeof(int))]; + struct iovec iov[2] = { { &status, sizeof(status) }, { out, out_size ? *out_size : 0 } }; + struct msghdr msg = { NULL, 0, iov, (out && out_size) ? 2 : 1, + recv_fd ? control : NULL, recv_fd ? sizeof(control) : 0, 0 }; + struct cmsghdr *cmsg; + + pthread_mutex_lock( &device_mutex ); + + if (recv_fd) *recv_fd = -1; + + if (device_fd == -1) + { + device_fd = socket( AF_UNIX, SOCK_SEQPACKET, 0 ); + if (device_fd < 0) goto done; + if (connect( device_fd, (const struct sockaddr *)&ipc_addr, IPC_SOCKET_ADDR_LEN ) < 0) + { + close( device_fd ); + device_fd = -1; + goto done; + } + } + + ret = writev( device_fd, (struct iovec[]){ { &code, sizeof(code) }, { in, in_size } }, 2 ); + if (ret <= 0 || ret != sizeof(code) + in_size) goto disconnected; + + ret = recvmsg( device_fd, &msg, 0 ); + if (ret <= 0 || ret < sizeof(status)) goto disconnected; + + if (out && out_size) *out_size = ret - sizeof(status); + err = status; + + if (recv_fd) + for (cmsg = CMSG_FIRSTHDR( &msg ); cmsg; cmsg = CMSG_NXTHDR( &msg, cmsg )) + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && + cmsg->cmsg_len >= CMSG_LEN(sizeof(int))) + { + memcpy( recv_fd, CMSG_DATA(cmsg), sizeof(int) ); + break; + } + + goto done; + +disconnected: + close( device_fd ); + device_fd = -1; + WARN( "parent process is gone\n" ); + NtTerminateProcess( 0, 1 ); + err = -ENOENT; + +done: + pthread_mutex_unlock( &device_mutex ); + return err; +} + static void win_incRef( struct android_native_base_t *base ) { struct native_win_wrapper *win = (struct native_win_wrapper *)base; @@ -1120,7 +1329,7 @@ static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuff res.buffer_id = -1; res.generation = 0; - ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size, NULL ); + ret = android_ioctl_old( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size, NULL ); if (ret) return ret; if (size < sizeof(res)) return -EINVAL; diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 8e6c700870a..e6efec88998 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -326,6 +326,7 @@ static const struct user_driver_funcs android_drv_funcs = static const JNINativeMethod methods[] = { + { "wine_looper_init", "()V", looper_init }, { "wine_desktop_changed", "(II)V", desktop_changed }, { "wine_config_changed", "(I)V", config_changed }, { "wine_surface_changed", "(ILandroid/view/Surface;Z)V", surface_changed }, @@ -350,6 +351,11 @@ DECL_FUNCPTR( AHardwareBuffer_unlock ); DECL_FUNCPTR( AHardwareBuffer_recvHandleFromUnixSocket ); DECL_FUNCPTR( AHardwareBuffer_sendHandleToUnixSocket ); DECL_FUNCPTR( ANativeWindowBuffer_getHardwareBuffer ); +DECL_FUNCPTR( ALooper_acquire ); +DECL_FUNCPTR( ALooper_forThread ); +DECL_FUNCPTR( ALooper_addFd ); +DECL_FUNCPTR( ALooper_removeFd ); +DECL_FUNCPTR( ALooper_release ); static void load_android_libs(void) { @@ -378,6 +384,11 @@ static void load_android_libs(void) LOAD_FUNCPTR( libandroid, AHardwareBuffer_recvHandleFromUnixSocket ); LOAD_FUNCPTR( libandroid, AHardwareBuffer_sendHandleToUnixSocket ); LOAD_FUNCPTR( libandroid, ANativeWindowBuffer_getHardwareBuffer ); + LOAD_FUNCPTR( libandroid, ALooper_acquire ); + LOAD_FUNCPTR( libandroid, ALooper_forThread ); + LOAD_FUNCPTR( libandroid, ALooper_addFd ); + LOAD_FUNCPTR( libandroid, ALooper_removeFd ); + LOAD_FUNCPTR( libandroid, ALooper_release ); } #undef DECL_FUNCPTR -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Switch dequeueBuffer to the socket-based ioctl transport. Replace the HANDLE duplication path using NtDuplicateObject and wineserver with direct fd passing over a UNIX socket. The ioctl is now handled entirely on the new dispatch thread and no longer depends on Wine TEB-based handle conversion. This completes the dequeueBuffer transition that was previously kept on the old transport for bisect safety. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 58 +++++------------------------------ 1 file changed, 8 insertions(+), 50 deletions(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index c57d5ea1bc6..e055dbe9381 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -177,8 +177,6 @@ struct ioctl_android_window_pos_changed struct ioctl_android_dequeueBuffer { struct ioctl_header hdr; - HANDLE handle; - DWORD pid; int buffer_id; int generation; }; @@ -652,14 +650,11 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; - res->handle = 0; res->buffer_id = -1; res->generation = 0; *ret_size = sizeof(*res); - wrap_java_call(); ret = parent->dequeueBuffer( parent, &buffer, &fence ); - unwrap_java_call(); if (ret) { LOG( ERR, "%08x failed %d\n", res->hdr.hwnd, ret ); @@ -677,15 +672,10 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO res->buffer_id = register_buffer( win_data, ahb, &is_new ); res->generation = win_data->generation; - res->handle = 0; if (is_new) { int sv[2] = { -1, -1 }; - HANDLE local = 0; - OBJECT_ATTRIBUTES attr = { .Length = sizeof(attr) }; - CLIENT_ID cid = { .UniqueProcess = UlongToHandle( res->pid ) }; - HANDLE process; if (!ahb) { @@ -699,37 +689,16 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO return STATUS_UNSUCCESSFUL; } - if (NtOpenProcess( &process, PROCESS_DUP_HANDLE, &attr, &cid )) - { - close( sv[0] ); - close( sv[1] ); - wait_fence_and_close( fence ); - return STATUS_UNSUCCESSFUL; - } - - if (!wine_server_fd_to_handle( dup(sv[1]), GENERIC_READ | SYNCHRONIZE, 0, &local )) - { - NTSTATUS status = NtDuplicateObject( GetCurrentProcess(), local, process, &res->handle, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ); - if (status && local) NtClose( local ); - } - - NtClose( process ); - close( sv[1] ); - - if (!res->handle) - { - close( sv[0] ); - wait_fence_and_close( fence ); - return STATUS_UNSUCCESSFUL; - } - ret = pAHardwareBuffer_sendHandleToUnixSocket( ahb, sv[0] ); close( sv[0] ); if (ret) { + close( sv[1] ); wait_fence_and_close( fence ); return android_error_to_status( ret ); } + + *reply_fd = sv[1]; } wait_fence_and_close( fence ); @@ -1320,35 +1289,24 @@ static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuff struct native_win_wrapper *win = (struct native_win_wrapper *)window; struct ioctl_android_dequeueBuffer res = {0}; DWORD size = sizeof(res); - int ret; + int ret, buffer_fd = -1; res.hdr.hwnd = HandleToLong( win->hwnd ); res.hdr.opengl = win->opengl; - res.pid = GetCurrentProcessId(); - res.handle = 0; res.buffer_id = -1; res.generation = 0; - ret = android_ioctl_old( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size, NULL ); + ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, &res, size, &res, &size, &buffer_fd ); if (ret) return ret; if (size < sizeof(res)) return -EINVAL; if (res.buffer_id < 0 || res.buffer_id >= NB_CACHED_BUFFERS) return -EINVAL; - if (res.handle) + if (buffer_fd != -1) { AHardwareBuffer *ahb = NULL; - int fd; - - if (wine_server_handle_to_fd( res.handle, GENERIC_READ | SYNCHRONIZE, &fd, NULL )) - { - NtClose( res.handle ); - return -EINVAL; - } - NtClose( res.handle ); - - ret = pAHardwareBuffer_recvHandleFromUnixSocket( fd, &ahb ); - close( fd ); + ret = pAHardwareBuffer_recvHandleFromUnixSocket( buffer_fd, &ahb ); + close( buffer_fd ); if (ret) return ret; if (win->buffers[res.buffer_id].self) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Remove the old wineandroid ioctl transport based on unixlib calls and the ntoskrnl device/IRP dispatch path. This drops the android_dispatch_ioctl entrypoint, the driver creation code, and the unixlib call table, along with the associated device thread and callback-based startup path. With the socket-based dispatch thread now handling all ioctls, the old HANDLE-based transport is no longer needed. Also remove the remaining artifacts of the old execution model, including the global JNIEnv, thread tracking, and the wrap_java_call/unwrap_java_call helpers used to work around JVM/Wine TLS conflicts. Simplify initialization accordingly by using __wine_unix_lib_init() directly, making dllmain.c consistent with winex11.drv. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/android.h | 11 +-- dlls/wineandroid.drv/device.c | 147 +-------------------------------- dlls/wineandroid.drv/dllmain.c | 73 +--------------- dlls/wineandroid.drv/init.c | 16 +--- dlls/wineandroid.drv/unixlib.h | 31 ------- 5 files changed, 8 insertions(+), 270 deletions(-) delete mode 100644 dlls/wineandroid.drv/unixlib.h diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 4882ca91f8b..c79ce31a046 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -35,7 +35,8 @@ #include "winbase.h" #include "ntgdi.h" #include "wine/gdi_driver.h" -#include "unixlib.h" +#include "ntuser.h" +#include "wine/unixlib.h" #include "android_native.h" @@ -120,13 +121,6 @@ extern void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_h extern ANativeWindow *get_client_window( HWND hwnd ); extern BOOL has_client_surface( HWND hwnd ); -/* unixlib interface */ - -extern NTSTATUS android_dispatch_ioctl( void *arg ); -extern NTSTATUS android_java_init( void *arg ); -extern NTSTATUS android_java_uninit( void *arg ); -extern UINT64 start_device_callback; - extern unsigned int screen_width; extern unsigned int screen_height; extern RECT virtual_screen_rect; @@ -203,7 +197,6 @@ int send_event( const union event_data *data ); extern JavaVM *java_vm; extern jobject java_object; -extern unsigned short java_gdt_sel; /* string helpers */ diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index e055dbe9381..0029cd48f4f 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -77,8 +77,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(android); #define SYNC_IOC_WAIT _IOW('>', 0, __s32) #endif -static HANDLE thread; -static JNIEnv *jni_env; static HWND capture_window; static HWND desktop_window; @@ -237,49 +235,6 @@ struct ioctl_android_set_cursor int bits[1]; }; - -static inline BOOL is_in_desktop_process(void) -{ - return thread != NULL; -} - -#ifdef __i386__ /* the Java VM uses %fs/%gs for its own purposes, so we need to wrap the calls */ - -static WORD orig_fs, java_fs; -static inline void wrap_java_call(void) { __asm__( "mov %0,%%fs" :: "r" (java_fs) ); } -static inline void unwrap_java_call(void) { __asm__( "mov %0,%%fs" :: "r" (orig_fs) ); } -static inline void init_java_thread( JavaVM *java_vm, JNIEnv** env ) -{ - java_fs = java_gdt_sel; - __asm__( "mov %%fs,%0" : "=r" (orig_fs) ); - __asm__( "mov %0,%%fs" :: "r" (java_fs) ); - (*java_vm)->AttachCurrentThread( java_vm, env, 0 ); - if (!java_gdt_sel) __asm__( "mov %%fs,%0" : "=r" (java_fs) ); - __asm__( "mov %0,%%fs" :: "r" (orig_fs) ); -} - -#elif defined(__x86_64__) - -#include <asm/prctl.h> -#include <asm/unistd.h> -static void *orig_teb, *java_teb; -static inline int arch_prctl( int func, void *ptr ) { return syscall( __NR_arch_prctl, func, ptr ); } -static inline void wrap_java_call(void) { arch_prctl( ARCH_SET_GS, java_teb ); } -static inline void unwrap_java_call(void) { arch_prctl( ARCH_SET_GS, orig_teb ); } -static inline void init_java_thread( JavaVM *java_vm, JNIEnv** env ) -{ - arch_prctl( ARCH_GET_GS, &orig_teb ); - (*java_vm)->AttachCurrentThread( java_vm, env, 0 ); - arch_prctl( ARCH_GET_GS, &java_teb ); - arch_prctl( ARCH_SET_GS, orig_teb ); -} - -#else -static inline void wrap_java_call(void) { } -static inline void unwrap_java_call(void) { } -static inline void init_java_thread( JavaVM *java_vm, JNIEnv** env ) { (*java_vm)->AttachCurrentThread( java_vm, env, 0 ); } -#endif /* __i386__ */ - static struct native_win_data *data_map[65536]; static unsigned int data_map_idx( HWND hwnd, BOOL opengl ) @@ -565,12 +520,9 @@ static void create_desktop_view( JNIEnv* env ) static jmethodID method; jobject object; - wrap_java_call(); - if (!(object = load_java_method( env, &method, "createDesktopView", "()V" ))) goto end; + if (!(object = load_java_method( env, &method, "createDesktopView", "()V" ))) return; (*env)->CallVoidMethod( env, object, method ); -end: - unwrap_java_call(); } static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) @@ -933,57 +885,6 @@ static const ioctl_func ioctl_funcs[] = setCursor_ioctl, /* IOCTL_SET_CURSOR */ }; -NTSTATUS android_dispatch_ioctl( void *arg ) -{ - IRP *irp = arg; - IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); - DWORD code = (irpsp->Parameters.DeviceIoControl.IoControlCode - ANDROID_IOCTL(0)) >> 2; - - if (code < NB_IOCTLS) - { - struct ioctl_header *header = irp->AssociatedIrp.SystemBuffer; - DWORD in_size = irpsp->Parameters.DeviceIoControl.InputBufferLength; - ioctl_func func = ioctl_funcs[code]; - - if (in_size >= sizeof(*header)) - { - int reply_fd = -1; - irp->IoStatus.Information = 0; - pthread_mutex_lock(&dispatch_ioctl_lock); - irp->IoStatus.Status = func( jni_env, irp->AssociatedIrp.SystemBuffer, in_size, - irpsp->Parameters.DeviceIoControl.OutputBufferLength, - &irp->IoStatus.Information, &reply_fd ); - pthread_mutex_unlock(&dispatch_ioctl_lock); - } - else irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - } - else - { - FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode ); - irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - } - return STATUS_SUCCESS; -} - -NTSTATUS android_java_init( void *arg ) -{ - if (!java_vm) return STATUS_UNSUCCESSFUL; /* not running under Java */ - - init_java_thread( java_vm, &jni_env ); - create_desktop_view( jni_env ); - return STATUS_SUCCESS; -} - -NTSTATUS android_java_uninit( void *arg ) -{ - if (!java_vm) return STATUS_UNSUCCESSFUL; /* not running under Java */ - - wrap_java_call(); - (*java_vm)->DetachCurrentThread( java_vm ); - unwrap_java_call(); - return STATUS_SUCCESS; -} - static ALooper *looper; static JNIEnv *looper_env; /* JNIEnv for the main thread looper. Must only be used from that thread. */ @@ -1143,15 +1044,14 @@ static void *bootstrap_looper_thread( void *arg ) abort(); } + create_desktop_view( env ); + (*java_vm)->DetachCurrentThread( java_vm ); return NULL; } void start_android_device(void) { - void *ret_ptr; - ULONG ret_len; - struct dispatch_callback_params params = {.callback = start_device_callback}; pthread_t t; log_flags = __wine_dbg_get_channel_flags(&__wine_dbch_android); @@ -1168,50 +1068,12 @@ void start_android_device(void) LOG( ERR, "Failed to spawn looper bootstrap thread\n" ); abort(); } - - if (KeUserDispatchCallback( ¶ms, sizeof(params), &ret_ptr, &ret_len )) return; - if (ret_len == sizeof(thread)) thread = *(HANDLE *)ret_ptr; - return; } /* Client-side ioctl support */ -static int android_ioctl_old( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *reply_fd ) -{ - static const WCHAR deviceW[] = { '\\','D','e','v','i','c','e','\\','W','i','n','e','A','n','d','r','o','i','d', 0 }; - static HANDLE device; - IO_STATUS_BLOCK iosb; - NTSTATUS status; - - if (!device) - { - OBJECT_ATTRIBUTES attr; - UNICODE_STRING name = RTL_CONSTANT_STRING( deviceW ); - IO_STATUS_BLOCK io; - NTSTATUS status; - HANDLE file; - - InitializeObjectAttributes( &attr, &name, OBJ_CASE_INSENSITIVE, NULL, NULL ); - status = NtCreateFile( &file, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, - FILE_NON_DIRECTORY_FILE, NULL, 0 ); - if (status) return -ENOENT; - if (InterlockedCompareExchangePointer( &device, file, NULL )) NtClose( file ); - } - - status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &iosb, ANDROID_IOCTL(code), - in, in_size, out, out_size ? *out_size : 0 ); - if (status == STATUS_FILE_DELETED) - { - WARN( "parent process is gone\n" ); - NtTerminateProcess( 0, 1 ); - } - if (out_size) *out_size = iosb.Information; - return status_to_android_error( status ); -} - static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size, int *recv_fd ) { static int device_fd = -1; @@ -1683,8 +1545,5 @@ int ioctl_set_cursor( int id, int width, int height, */ void ANDROID_SetDesktopWindow( HWND hwnd ) { - if (!is_in_desktop_process()) - return; - TRACE( "%p\n", hwnd ); desktop_window = hwnd; } diff --git a/dlls/wineandroid.drv/dllmain.c b/dlls/wineandroid.drv/dllmain.c index dd2493c6f55..b83f35e84ba 100644 --- a/dlls/wineandroid.drv/dllmain.c +++ b/dlls/wineandroid.drv/dllmain.c @@ -19,76 +19,9 @@ */ #include <stdarg.h> -#include "ntstatus.h" #include "windef.h" #include "winbase.h" -#include "winternl.h" -#include "winioctl.h" -#include "ddk/wdm.h" -#include "unixlib.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(android); - - -extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); -static HANDLE stop_event; - - -static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) -{ - NTSTATUS status = ANDROID_CALL( dispatch_ioctl, irp ); - IoCompleteRequest( irp, IO_NO_INCREMENT ); - return status; -} - -static NTSTATUS CALLBACK init_android_driver( DRIVER_OBJECT *driver, UNICODE_STRING *name ) -{ - UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"\\Device\\WineAndroid" ); - DEVICE_OBJECT *device; - - driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ioctl_callback; - - return IoCreateDevice( driver, 0, &nameW, 0, 0, FALSE, &device ); -} - -static DWORD CALLBACK device_thread( void *arg ) -{ - HANDLE start_event = arg; - UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"\\Driver\\WineAndroid" ); - NTSTATUS status; - DWORD ret; - - TRACE( "starting process %lx\n", GetCurrentProcessId() ); - - if (ANDROID_CALL( java_init, NULL )) return 0; /* not running under Java */ - - if ((status = IoCreateDriver( &nameW, init_android_driver ))) - { - FIXME( "failed to create driver error %lx\n", status ); - return status; - } - - stop_event = CreateEventW( NULL, TRUE, FALSE, NULL ); - SetEvent( start_event ); - - ret = wine_ntoskrnl_main_loop( stop_event ); - - ANDROID_CALL( java_uninit, NULL ); - return ret; -} - -static NTSTATUS WINAPI android_start_device(void *param, ULONG size) -{ - HANDLE handles[2]; - - handles[0] = CreateEventW( NULL, TRUE, FALSE, NULL ); - handles[1] = CreateThread( NULL, 0, device_thread, handles[0], 0, NULL ); - WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); - CloseHandle( handles[0] ); - return NtCallbackReturn( &handles[1], sizeof(handles[1]), STATUS_SUCCESS ); -} - +#include "wine/unixlib.h" /*********************************************************************** * dll initialisation routine @@ -98,7 +31,5 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) if (reason != DLL_PROCESS_ATTACH) return TRUE; DisableThreadLibraryCalls( inst ); - if (__wine_init_unix_call()) return FALSE; - - return !ANDROID_CALL( init, (void *)(UINT_PTR)android_start_device ); + return !__wine_init_unix_call(); } diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index e6efec88998..4ad3b42b0f5 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -50,8 +50,6 @@ static const unsigned int screen_bpp = 32; /* we don't support other modes */ static RECT monitor_rc_work; static int device_init_done; -UINT64 start_device_callback; - typedef struct { struct gdi_physdev dev; @@ -394,7 +392,7 @@ static void load_android_libs(void) #undef DECL_FUNCPTR #undef LOAD_FUNCPTR -static HRESULT android_init( void *arg ) +NTSTATUS __wine_unix_lib_init(void) { pthread_mutexattr_t attr; jclass class; @@ -407,8 +405,6 @@ static HRESULT android_init( void *arg ) pthread_mutex_init( &win_data_mutex, &attr ); pthread_mutexattr_destroy( &attr ); - start_device_callback = (UINT64)(UINT_PTR)arg; - if (java_vm) /* running under Java */ { #ifdef __i386__ @@ -428,13 +424,3 @@ static HRESULT android_init( void *arg ) return STATUS_SUCCESS; } -const unixlib_entry_t __wine_unix_call_funcs[] = -{ - android_dispatch_ioctl, - android_init, - android_java_init, - android_java_uninit, -}; - - -C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count ); diff --git a/dlls/wineandroid.drv/unixlib.h b/dlls/wineandroid.drv/unixlib.h deleted file mode 100644 index 7549541e48e..00000000000 --- a/dlls/wineandroid.drv/unixlib.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2022 Jacek Caban for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "ntuser.h" -#include "wine/unixlib.h" - -enum android_funcs -{ - unix_dispatch_ioctl, - unix_init, - unix_java_init, - unix_java_uninit, - unix_funcs_count -}; - -#define ANDROID_CALL(func, params) WINE_UNIX_CALL( unix_ ## func, params ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Return ioctl handler errors directly instead of converting them between Android errno values and NTSTATUS. The socket-based ioctl path no longer goes through Wine's device/IRP infrastructure, so the old android_error_to_status() and status_to_android_error() mappings are no longer needed. Make the handlers return their native error values directly and pass them through handle_ioctl_message() unchanged. This simplifies the ioctl path and removes the leftover error mapping layer from the old transport model. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 183 ++++++++++++---------------------- 1 file changed, 66 insertions(+), 117 deletions(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 0029cd48f4f..34424009afd 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -36,7 +36,6 @@ #include <sys/uio.h> #include <unistd.h> -#include "ntstatus.h" #include "windef.h" #include "winbase.h" #include "winternl.h" @@ -451,53 +450,6 @@ HWND get_capture_window(void) return capture_window; } -static NTSTATUS android_error_to_status( int err ) -{ - switch (err) - { - case 0: return STATUS_SUCCESS; - case -ENOMEM: return STATUS_NO_MEMORY; - case -ENOSYS: return STATUS_NOT_SUPPORTED; - case -EINVAL: return STATUS_INVALID_PARAMETER; - case -ENOENT: return STATUS_INVALID_HANDLE; - case -EPERM: return STATUS_ACCESS_DENIED; - case -ENODEV: return STATUS_NO_SUCH_DEVICE; - case -EEXIST: return STATUS_DUPLICATE_NAME; - case -EPIPE: return STATUS_PIPE_DISCONNECTED; - case -ENODATA: return STATUS_NO_MORE_FILES; - case -ETIMEDOUT: return STATUS_IO_TIMEOUT; - case -EBADMSG: return STATUS_INVALID_DEVICE_REQUEST; - case -EWOULDBLOCK: return STATUS_DEVICE_NOT_READY; - default: - LOG( FIXME, "unmapped error %d\n", err ); - return STATUS_UNSUCCESSFUL; - } -} - -static int status_to_android_error( unsigned int status ) -{ - switch (status) - { - case STATUS_SUCCESS: return 0; - case STATUS_NO_MEMORY: return -ENOMEM; - case STATUS_NOT_SUPPORTED: return -ENOSYS; - case STATUS_INVALID_PARAMETER: return -EINVAL; - case STATUS_BUFFER_OVERFLOW: return -EINVAL; - case STATUS_INVALID_HANDLE: return -ENOENT; - case STATUS_ACCESS_DENIED: return -EPERM; - case STATUS_NO_SUCH_DEVICE: return -ENODEV; - case STATUS_DUPLICATE_NAME: return -EEXIST; - case STATUS_PIPE_DISCONNECTED: return -EPIPE; - case STATUS_NO_MORE_FILES: return -ENODATA; - case STATUS_IO_TIMEOUT: return -ETIMEDOUT; - case STATUS_INVALID_DEVICE_REQUEST: return -EBADMSG; - case STATUS_DEVICE_NOT_READY: return -EWOULDBLOCK; - default: - FIXME( "unmapped status %08x\n", status ); - return -EINVAL; - } -} - static jobject load_java_method( JNIEnv* env, jmethodID *method, const char *name, const char *args ) { if (!*method) @@ -525,69 +477,69 @@ static void create_desktop_view( JNIEnv* env ) (*env)->CallVoidMethod( env, object, method ); } -static NTSTATUS createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int createWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; struct ioctl_android_create_window *res = data; struct native_win_data *win_data; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; if (!(win_data = create_native_win_data( LongToHandle(res->hdr.hwnd), res->hdr.opengl ))) - return STATUS_NO_MEMORY; + return -ENOMEM; LOG( TRACE, "hwnd %08x opengl %u parent %08x\n", res->hdr.hwnd, res->hdr.opengl, res->parent ); - if (!(object = load_java_method( env, &method, "createWindow", "(IZZI)V" ))) return STATUS_NOT_SUPPORTED; + if (!(object = load_java_method( env, &method, "createWindow", "(IZZI)V" ))) return -ENOSYS; (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->is_desktop, res->hdr.opengl, res->parent ); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int destroyWindow_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; struct ioctl_android_destroy_window *res = data; struct native_win_data *win_data; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; win_data = get_ioctl_native_win_data( &res->hdr ); LOG( TRACE, "hwnd %08x opengl %u\n", res->hdr.hwnd, res->hdr.opengl ); - if (!(object = load_java_method( env, &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED; + if (!(object = load_java_method( env, &method, "destroyWindow", "(I)V" ))) return -ENOSYS; (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd ); if (win_data) free_native_win_data( win_data ); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int windowPosChanged_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; struct ioctl_android_window_pos_changed *res = data; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; LOG( TRACE, "hwnd %08x win " DBGSTR_RECT_FMT " client " DBGSTR_RECT_FMT " visible " DBGSTR_RECT_FMT " style %08x flags %08x after %08x owner %08x\n", res->hdr.hwnd, DBGSTR_RECT(&res->window_rect), DBGSTR_RECT(&res->client_rect), DBGSTR_RECT(&res->visible_rect), res->style, res->flags, res->after, res->owner ); if (!(object = load_java_method( env, &method, "windowPosChanged", "(IIIIIIIIIIIIIIIII)V" ))) - return STATUS_NOT_SUPPORTED; + return -ENOSYS; (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->flags, res->after, res->owner, res->style, res->window_rect.left, res->window_rect.top, res->window_rect.right, res->window_rect.bottom, res->client_rect.left, res->client_rect.top, res->client_rect.right, res->client_rect.bottom, res->visible_rect.left, res->visible_rect.top, res->visible_rect.right, res->visible_rect.bottom ); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ANativeWindow *parent; struct ioctl_android_dequeueBuffer *res = data; @@ -596,11 +548,10 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO AHardwareBuffer *ahb = NULL; int fence, ret, is_new; - if (out_size < sizeof( *res )) return STATUS_BUFFER_OVERFLOW; - if (in_size < sizeof(res->hdr)) return STATUS_INVALID_PARAMETER; + if (out_size < sizeof( *res ) || in_size < sizeof(res->hdr)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; - if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; + if (!(parent = win_data->parent)) return -EWOULDBLOCK; res->buffer_id = -1; res->generation = 0; @@ -610,7 +561,7 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO if (ret) { LOG( ERR, "%08x failed %d\n", res->hdr.hwnd, ret ); - return android_error_to_status( ret ); + return ret; } if (!buffer) @@ -647,17 +598,17 @@ static NTSTATUS dequeueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWO { close( sv[1] ); wait_fence_and_close( fence ); - return android_error_to_status( ret ); + return ret; } *reply_fd = sv[1]; } wait_fence_and_close( fence ); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_cancelBuffer *res = data; struct ANativeWindow *parent; @@ -665,20 +616,20 @@ static NTSTATUS cancelBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWOR struct native_win_data *win_data; int ret; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; - if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; - if (res->generation != win_data->generation) return STATUS_SUCCESS; /* obsolete buffer, ignore */ + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; + if (!(parent = win_data->parent)) return -EWOULDBLOCK; + if (res->generation != win_data->generation) return 0; /* obsolete buffer, ignore */ - if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return STATUS_INVALID_HANDLE; + if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return -ENOENT; LOG( TRACE, "%08x buffer %p\n", res->hdr.hwnd, buffer ); ret = parent->cancelBuffer( parent, buffer, -1 ); - return android_error_to_status( ret ); + return ret; } -static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_queueBuffer *res = data; struct ANativeWindow *parent; @@ -686,48 +637,47 @@ static NTSTATUS queueBuffer_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD struct native_win_data *win_data; int ret; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; - if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; - if (res->generation != win_data->generation) return STATUS_SUCCESS; /* obsolete buffer, ignore */ + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; + if (!(parent = win_data->parent)) return -EWOULDBLOCK; + if (res->generation != win_data->generation) return 0; /* obsolete buffer, ignore */ - if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return STATUS_INVALID_HANDLE; + if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return -ENOENT; LOG( TRACE, "%08x buffer %p\n", res->hdr.hwnd, buffer ); ret = parent->queueBuffer( parent, buffer, -1 ); - return android_error_to_status( ret ); + return ret; } -static NTSTATUS query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int query_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_query *res = data; struct ANativeWindow *parent; struct native_win_data *win_data; int ret; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; - if (out_size < sizeof(*res)) return STATUS_BUFFER_OVERFLOW; + if (in_size < sizeof(*res) || out_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; - if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; + if (!(parent = win_data->parent)) return -EWOULDBLOCK; *ret_size = sizeof( *res ); ret = parent->query( parent, res->what, &res->value ); - return android_error_to_status( ret ); + return ret; } -static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_perform *res = data; struct ANativeWindow *parent; struct native_win_data *win_data; int ret = -ENOENT; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; - if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY; + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; + if (!(parent = win_data->parent)) return -EWOULDBLOCK; switch (res->operation) { @@ -781,79 +731,79 @@ static NTSTATUS perform_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out LOG( FIXME, "unsupported perform op %d\n", res->operation ); break; } - return android_error_to_status( ret ); + return ret; } -static NTSTATUS setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int setSwapInterval_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_set_swap_interval *res = data; struct ANativeWindow *parent; struct native_win_data *win_data; int ret; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; win_data->swap_interval = res->interval; - if (!(parent = win_data->parent)) return STATUS_SUCCESS; + if (!(parent = win_data->parent)) return 0; ret = parent->setSwapInterval( parent, res->interval ); - return android_error_to_status( ret ); + return ret; } -static NTSTATUS setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int setWindowParent_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; struct ioctl_android_set_window_parent *res = data; struct native_win_data *win_data; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return -ENOENT; LOG( TRACE, "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent ); - if (!(object = load_java_method( env, &method, "setParent", "(II)V" ))) return STATUS_NOT_SUPPORTED; + if (!(object = load_java_method( env, &method, "setParent", "(II)V" ))) return -ENOSYS; (*env)->CallVoidMethod( env, object, method, res->hdr.hwnd, res->parent ); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS setCapture_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int setCapture_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { struct ioctl_android_set_capture *res = data; - if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(*res)) return -EINVAL; - if (res->hdr.hwnd && !get_ioctl_native_win_data( &res->hdr )) return STATUS_INVALID_HANDLE; + if (res->hdr.hwnd && !get_ioctl_native_win_data( &res->hdr )) return -ENOENT; LOG( TRACE, "hwnd %08x\n", res->hdr.hwnd ); InterlockedExchangePointer( (void **)&capture_window, LongToHandle( res->hdr.hwnd )); - return STATUS_SUCCESS; + return 0; } -static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) +static int setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ) { static jmethodID method; jobject object; int size; struct ioctl_android_set_cursor *res = data; - if (in_size < offsetof( struct ioctl_android_set_cursor, bits )) return STATUS_INVALID_PARAMETER; + if (in_size < offsetof( struct ioctl_android_set_cursor, bits )) return -EINVAL; if (res->width < 0 || res->height < 0 || res->width > 256 || res->height > 256) - return STATUS_INVALID_PARAMETER; + return -EINVAL; size = res->width * res->height; if (in_size != offsetof( struct ioctl_android_set_cursor, bits[size] )) - return STATUS_INVALID_PARAMETER; + return -EINVAL; LOG( TRACE, "hwnd %08x size %d\n", res->hdr.hwnd, size ); if (!(object = load_java_method( env, &method, "setCursor", "(IIIII[I)V" ))) - return STATUS_NOT_SUPPORTED; + return -ENOSYS; if (size) { @@ -865,10 +815,10 @@ static NTSTATUS setCursor_ioctl( JNIEnv* env, void *data, DWORD in_size, DWORD o } else (*env)->CallVoidMethod( env, object, method, res->id, 0, 0, 0, 0, NULL ); - return STATUS_SUCCESS; + return 0; } -typedef NTSTATUS (*ioctl_func)( JNIEnv* env, void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ); +typedef int (*ioctl_func)( JNIEnv* env, void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size, int *reply_fd ); static const ioctl_func ioctl_funcs[] = { createWindow_ioctl, /* IOCTL_CREATE_WINDOW */ @@ -932,8 +882,7 @@ static int handle_ioctl_message( JNIEnv *env, int fd ) if (ret >= sizeof(struct ioctl_header)) { pthread_mutex_lock( &dispatch_ioctl_lock ); - status = status_to_android_error( - ioctl_funcs[code]( env, buffer, ret, sizeof(buffer), &reply_size, &reply_fd ) ); + status = ioctl_funcs[code]( env, buffer, ret, sizeof(buffer), &reply_size, &reply_fd ); pthread_mutex_unlock( &dispatch_ioctl_lock ); } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10806
participants (2)
-
Twaik Yont -
Twaik Yont (@twaik)