From: Aric Stewart Subject: [PATCH 2/5] programs/winedevice.exe: allow loading multiple devices on the command line Message-Id: <51f42346-070d-9c41-60ab-3a2d091970d5@codeweavers.com> Date: Tue, 9 Aug 2016 11:40:20 -0500 Signed-off-by: Aric Stewart --- programs/winedevice/device.c | 92 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index 771a0c1..636ab2f 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -40,9 +40,27 @@ WINE_DECLARE_DEBUG_CHANNEL(relay); extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); +typedef struct device_ { + WCHAR driver_name[255]; + DRIVER_OBJECT *driver_obj; +} device; + static SERVICE_STATUS_HANDLE service_handle; static HANDLE stop_event; +static device *devices = NULL; +static DWORD devices_size = 0; +static DWORD device_count = 0; + +static CRITICAL_SECTION group_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &group_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": winedevice_group") } +}; +static CRITICAL_SECTION group_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + /* find the LDR_MODULE corresponding to the driver module */ static LDR_MODULE *find_ldr_module( HMODULE module ) { @@ -304,7 +322,7 @@ static NTSTATUS create_driver(const WCHAR *driver_name, DRIVER_OBJECT **driver_o static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context ) { SERVICE_STATUS status; - const WCHAR *driver_name = context; + const WCHAR *service_name = context; status.dwServiceType = SERVICE_WIN32; status.dwControlsAccepted = SERVICE_ACCEPT_STOP; @@ -317,14 +335,14 @@ static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_ { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: - WINE_TRACE( "shutting down %s\n", wine_dbgstr_w(driver_name) ); + WINE_TRACE( "shutting down %s\n", wine_dbgstr_w(service_name) ); status.dwCurrentState = SERVICE_STOP_PENDING; status.dwControlsAccepted = 0; SetServiceStatus( service_handle, &status ); SetEvent( stop_event ); return NO_ERROR; default: - WINE_FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) ); + WINE_FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(service_name) ); status.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( service_handle, &status ); return NO_ERROR; @@ -334,14 +352,14 @@ static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { SERVICE_STATUS status; - const WCHAR *driver_name = argv[0]; - DRIVER_OBJECT *driver_obj; + const WCHAR* service_name = argv[0]; + int i; - WINE_TRACE( "starting service %s\n", wine_dbgstr_w(driver_name) ); + WINE_TRACE( "starting service %s\n", wine_dbgstr_w(service_name) ); stop_event = CreateEventW( NULL, TRUE, FALSE, NULL ); - service_handle = RegisterServiceCtrlHandlerExW( driver_name, service_handler, (void *)driver_name ); + service_handle = RegisterServiceCtrlHandlerExW( service_name, service_handler, (void *)service_name); if (!service_handle) return; @@ -354,38 +372,78 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) status.dwWaitHint = 10000; SetServiceStatus( service_handle, &status ); - if (create_driver( driver_name, &driver_obj ) == STATUS_SUCCESS) + if (device_count > 0) { - status.dwCurrentState = SERVICE_RUNNING; - status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; - SetServiceStatus( service_handle, &status ); - - wine_ntoskrnl_main_loop( stop_event ); - unload_driver( driver_obj ); + EnterCriticalSection(&group_cs); + for (i = 0; i < device_count; i++) + if (create_driver( devices[i].driver_name, &devices[i].driver_obj ) != STATUS_SUCCESS) + WINE_ERR( "driver %s failed to load\n", wine_dbgstr_w(devices[i].driver_name) ); + LeaveCriticalSection(&group_cs); } - else WINE_ERR( "driver %s failed to load\n", wine_dbgstr_w(driver_name) ); + + status.dwCurrentState = SERVICE_RUNNING; + status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + SetServiceStatus( service_handle, &status ); + + wine_ntoskrnl_main_loop( stop_event ); + + EnterCriticalSection(&group_cs); + for (i = 0; i < device_count; i++) + unload_driver( devices[i].driver_obj ); + device_count = 0; + LeaveCriticalSection(&group_cs); status.dwCurrentState = SERVICE_STOPPED; status.dwControlsAccepted = 0; SetServiceStatus( service_handle, &status ); - WINE_TRACE( "service %s stopped\n", wine_dbgstr_w(driver_name) ); + WINE_TRACE( "service %s stopped\n", wine_dbgstr_w(service_name) ); } int wmain( int argc, WCHAR *argv[] ) { SERVICE_TABLE_ENTRYW service_table[2]; + static WCHAR szGroupName[] = {'g','r','o','u','p','_',0}; + WCHAR *service_name; if (!argv[1]) { WINE_ERR( "missing device name, winedevice isn't supposed to be run manually\n" ); return 1; } + else + { + int i; + if (argc > 2) + { + service_name = HeapAlloc(GetProcessHeap(), 0, lstrlenW(argv[1]) * sizeof(WCHAR) + sizeof(szGroupName)); + lstrcpyW(service_name, szGroupName); + } + else + { + service_name = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(argv[1])+1) * sizeof(WCHAR)); + } + lstrcpyW(service_name, argv[1]); + + device_count = argc - 1; + devices_size = argc - 1; + devices = HeapAlloc(GetProcessHeap(), 0, sizeof(*devices) * devices_size); + if (!devices) + { + WINE_ERR("Failed to allocate group\n"); + return 1; + } + for (i = 1; i < argc; i++) + lstrcpyW(devices[i-1].driver_name, argv[i]); + } - service_table[0].lpServiceName = argv[1]; + service_table[0].lpServiceName = service_name; service_table[0].lpServiceProc = ServiceMain; service_table[1].lpServiceName = NULL; service_table[1].lpServiceProc = NULL; StartServiceCtrlDispatcherW( service_table ); + HeapFree( GetProcessHeap(), 0, devices ); + HeapFree( GetProcessHeap(), 0, service_name ); + DeleteCriticalSection(&group_cs); return 0; }