From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/wineandroid.drv/android.h | 3 ++ dlls/wineandroid.drv/device.c | 71 ++++++++------------------- dlls/wineandroid.drv/dllmain.c | 89 +++++++++++++++++++++++++++++++++- dlls/wineandroid.drv/init.c | 3 ++ dlls/wineandroid.drv/unixlib.h | 16 ++++++ 5 files changed, 130 insertions(+), 52 deletions(-)
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 2a09d4195ef..c73ab6bc765 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -115,6 +115,9 @@ extern void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_fla /* unixlib interface */
extern NTSTATUS android_create_desktop( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS android_dispatch_ioctl( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS android_java_init( void *arg ) DECLSPEC_HIDDEN; +extern NTSTATUS android_java_uninit( void *arg ) DECLSPEC_HIDDEN;
extern unsigned int screen_width DECLSPEC_HIDDEN; extern unsigned int screen_height DECLSPEC_HIDDEN; diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index b4f332d2cef..b49b691b27a 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -47,8 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(android); #define SYNC_IOC_WAIT _IOW('>', 0, __s32) #endif
-extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); -static HANDLE stop_event; static HANDLE thread; static JNIEnv *jni_env; static HWND capture_window; @@ -243,7 +241,8 @@ static inline BOOL is_in_desktop_process(void)
static inline DWORD current_client_id(void) { - return HandleToUlong( PsGetCurrentProcessId() ); + DWORD client_id = PtrToUlong( NtUserGetThreadInfo()->driver_data ); + return client_id ? client_id : GetCurrentProcessId(); }
static inline BOOL is_client_in_process(void) @@ -1116,8 +1115,10 @@ static const ioctl_func ioctl_funcs[] = setCursor_ioctl, /* IOCTL_SET_CURSOR */ };
-static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) +NTSTATUS android_dispatch_ioctl( void *arg ) { + struct ioctl_params *params = arg; + IRP *irp = params->irp; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); DWORD code = (irpsp->Parameters.DeviceIoControl.IoControlCode - ANDROID_IOCTL(0)) >> 2;
@@ -1130,9 +1131,11 @@ static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) if (in_size >= sizeof(*header)) { irp->IoStatus.Information = 0; + NtUserGetThreadInfo()->driver_data = UlongToHandle( params->client_id ); irp->IoStatus.u.Status = func( irp->AssociatedIrp.SystemBuffer, in_size, irpsp->Parameters.DeviceIoControl.OutputBufferLength, &irp->IoStatus.Information ); + NtUserGetThreadInfo()->driver_data = 0; } else irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; } @@ -1141,72 +1144,38 @@ static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode ); irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED; } - IoCompleteRequest( irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; }
-static NTSTATUS CALLBACK init_android_driver( DRIVER_OBJECT *driver, UNICODE_STRING *name ) +NTSTATUS android_java_init( void *arg ) { - static const WCHAR device_nameW[] = {'\','D','e','v','i','c','e','\','W','i','n','e','A','n','d','r','o','i','d',0 }; - static const WCHAR device_linkW[] = {'\','?','?','\','W','i','n','e','A','n','d','r','o','i','d',0 }; - - UNICODE_STRING nameW, linkW; - DEVICE_OBJECT *device; - NTSTATUS status; - - driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ioctl_callback; - - RtlInitUnicodeString( &nameW, device_nameW ); - RtlInitUnicodeString( &linkW, device_linkW ); - - if ((status = IoCreateDevice( driver, 0, &nameW, 0, 0, FALSE, &device ))) return status; - return IoCreateSymbolicLink( &linkW, &nameW ); -} - -static DWORD CALLBACK device_thread( void *arg ) -{ - static const WCHAR driver_nameW[] = {'\','D','r','i','v','e','r','\','W','i','n','e','A','n','d','r','o','i','d',0 }; - - HANDLE start_event = arg; - UNICODE_STRING nameW; - NTSTATUS status; JavaVM *java_vm; - DWORD ret; - - TRACE( "starting process %x\n", GetCurrentProcessId() );
- if (!(java_vm = *p_java_vm)) return 0; /* not running under Java */ + if (!(java_vm = *p_java_vm)) return STATUS_UNSUCCESSFUL; /* not running under Java */
init_java_thread( java_vm ); - create_desktop_window( NtUserGetDesktopWindow() ); + return STATUS_SUCCESS; +}
- RtlInitUnicodeString( &nameW, driver_nameW ); - if ((status = IoCreateDriver( &nameW, init_android_driver ))) - { - FIXME( "failed to create driver error %x\n", status ); - return status; - } - - stop_event = CreateEventW( NULL, TRUE, FALSE, NULL ); - SetEvent( start_event ); +NTSTATUS android_java_uninit( void *arg ) +{ + JavaVM *java_vm;
- ret = wine_ntoskrnl_main_loop( stop_event ); + if (!(java_vm = *p_java_vm)) return STATUS_UNSUCCESSFUL; /* not running under Java */
wrap_java_call(); (*java_vm)->DetachCurrentThread( java_vm ); unwrap_java_call(); - return ret; + return STATUS_SUCCESS; }
void start_android_device(void) { - HANDLE handles[2]; - - handles[0] = CreateEventW( NULL, TRUE, FALSE, NULL ); - handles[1] = thread = CreateThread( NULL, 0, device_thread, handles[0], 0, NULL ); - WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); - CloseHandle( handles[0] ); + /* FIXME: use KeUserModeCallback instead */ + NTSTATUS (WINAPI *func)(void *, ULONG) = + ((void **)NtCurrentTeb()->Peb->KernelCallbackTable)[client_start_device]; + func( NULL, 0 ); }
diff --git a/dlls/wineandroid.drv/dllmain.c b/dlls/wineandroid.drv/dllmain.c index 42719798f33..37539fa5756 100644 --- a/dlls/wineandroid.drv/dllmain.c +++ b/dlls/wineandroid.drv/dllmain.c @@ -19,9 +19,89 @@ */
#include <stdarg.h> +#include "ntstatus.h" +#define WIN32_NO_STATUS #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 HANDLE thread; + + +static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) +{ + struct ioctl_params params = { .irp = irp, .client_id = HandleToUlong(PsGetCurrentProcessId()) }; + NTSTATUS status = ANDROID_CALL( dispatch_ioctl, ¶ms ); + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return status; +} + +static NTSTATUS CALLBACK init_android_driver( DRIVER_OBJECT *driver, UNICODE_STRING *name ) +{ + static const WCHAR device_nameW[] = {'\','D','e','v','i','c','e','\','W','i','n','e','A','n','d','r','o','i','d',0 }; + static const WCHAR device_linkW[] = {'\','?','?','\','W','i','n','e','A','n','d','r','o','i','d',0 }; + + UNICODE_STRING nameW, linkW; + DEVICE_OBJECT *device; + NTSTATUS status; + + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ioctl_callback; + + RtlInitUnicodeString( &nameW, device_nameW ); + RtlInitUnicodeString( &linkW, device_linkW ); + + if ((status = IoCreateDevice( driver, 0, &nameW, 0, 0, FALSE, &device ))) return status; + return IoCreateSymbolicLink( &linkW, &nameW ); +} + +static DWORD CALLBACK device_thread( void *arg ) +{ + static const WCHAR driver_nameW[] = {'\','D','r','i','v','e','r','\','W','i','n','e','A','n','d','r','o','i','d',0 }; + + HANDLE start_event = arg; + UNICODE_STRING nameW; + NTSTATUS status; + DWORD ret; + + TRACE( "starting process %x\n", GetCurrentProcessId() ); + + if (ANDROID_CALL( java_init, NULL )) return 0; /* not running under Java */ + + RtlInitUnicodeString( &nameW, driver_nameW ); + if ((status = IoCreateDriver( &nameW, init_android_driver ))) + { + FIXME( "failed to create driver error %x\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] = thread = CreateThread( NULL, 0, device_thread, handles[0], 0, NULL ); + WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); + CloseHandle( handles[0] ); + return HandleToULong( thread ); +}
/*********************************************************************** @@ -29,10 +109,17 @@ */ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) { + void **callback_table; + if (reason == DLL_PROCESS_ATTACH) return TRUE;
DisableThreadLibraryCalls( inst ); - return !ANDROID_CALL(init, NULL); + if (ANDROID_CALL( init, NULL )) return FALSE; + + callback_table = NtCurrentTeb()->Peb->KernelCallbackTable; + callback_table[client_start_device] = android_start_device; + + return TRUE; }
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 3739d4e4cb4..b5f0b69fcec 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -604,7 +604,10 @@ static HRESULT android_init( void *arg ) const unixlib_entry_t __wine_unix_call_funcs[] = { android_create_desktop, + android_dispatch_ioctl, android_init, + android_java_init, + android_java_uninit, };
diff --git a/dlls/wineandroid.drv/unixlib.h b/dlls/wineandroid.drv/unixlib.h index 10fe401dea0..2838047f4fe 100644 --- a/dlls/wineandroid.drv/unixlib.h +++ b/dlls/wineandroid.drv/unixlib.h @@ -22,10 +22,26 @@ enum android_funcs { unix_create_desktop, + unix_dispatch_ioctl, unix_init, + unix_java_init, + unix_java_uninit, unix_funcs_count };
/* FIXME: Use __wine_unix_call when the rest of the stack is ready */ extern NTSTATUS unix_call( enum android_funcs func, void *arg ) DECLSPEC_HIDDEN; #define ANDROID_CALL(func, params) unix_call( unix_ ## func, params ) + +/* android_ioctl params */ +struct ioctl_params +{ + struct _IRP *irp; + DWORD client_id; +}; + + +enum +{ + client_start_device = NtUserDriverCallbackFirst, +};