Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 89 ++++++++++++++++++++++- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- programs/winedevice/device.c | 106 ++-------------------------- 3 files changed, 93 insertions(+), 104 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 685f7d4345b..b50886da137 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -894,16 +894,98 @@ static void unload_driver( struct wine_rb_entry *entry, void *context )
PEPROCESS PsInitialSystemProcess = NULL;
+static HANDLE stop_event; +static SERVICE_STATUS_HANDLE group_handle; + +static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) +{ + UNICODE_STRING service_name; + DWORD result = NO_ERROR; + WCHAR *str; + + if (!(str = heap_alloc( sizeof(servicesW) + wcslen(driver_name) * sizeof(WCHAR) ))) + return STATUS_NO_MEMORY; + + wcscpy( str, servicesW ); + wcscat( str, driver_name ); + RtlInitUnicodeString( &service_name, str ); + + switch (ctrl) + { + case SERVICE_CONTROL_START: + result = RtlNtStatusToDosError( ZwLoadDriver( &service_name ) ); + break; + + case SERVICE_CONTROL_STOP: + result = RtlNtStatusToDosError( ZwUnloadDriver( &service_name ) ); + break; + + default: + FIXME( "got driver ctrl %#x for %s\n", ctrl, debugstr_w(driver_name) ); + break; + } + + RtlFreeUnicodeString( &service_name ); + return result; +} + +static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, void *event_data, void *context ) +{ + if (ctrl & SERVICE_CONTROL_FORWARD_FLAG) + { + if (!event_data) return ERROR_INVALID_PARAMETER; + return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data ); + } + + switch (ctrl) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + TRACE( "shutting down\n" ); + set_service_status( group_handle, SERVICE_STOP_PENDING, 0 ); + SetEvent( stop_event ); + return NO_ERROR; + default: + FIXME( "got service ctrl %#x\n", ctrl ); + set_service_status( group_handle, SERVICE_RUNNING, + SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); + return NO_ERROR; + } +} + /*********************************************************************** * wine_ntoskrnl_main_loop (Not a Windows API) */ -NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) +NTSTATUS CDECL wine_ntoskrnl_main_loop(void) { HANDLE manager = get_device_manager(); struct dispatch_context context; NTSTATUS status = STATUS_SUCCESS; + WCHAR driver_dir[MAX_PATH]; + SC_HANDLE manager_handle; HANDLE handles[2];
+ if ((status = NtCreateEvent( &stop_event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ))) + return status; + + if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT ))) + { + ERR( "Failed to open service manager, error %u.\n", GetLastError() ); + return STATUS_UNSUCCESSFUL; + } + if (!(group_handle = RegisterServiceCtrlHandlerExW( L"winedevice", service_handler, NULL ))) + { + ERR( "Failed to register service control handler, error %u.\n", GetLastError() ); + CloseServiceHandle( manager_handle ); + return STATUS_UNSUCCESSFUL; + } + + GetSystemDirectoryW( driver_dir, MAX_PATH ); + wcscat( driver_dir, L"\drivers" ); + AddDllDirectory( driver_dir ); + + set_service_status( group_handle, SERVICE_RUNNING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); + context.handle = NULL; context.irp = NULL; context.in_size = 4096; @@ -986,6 +1068,11 @@ done: * their unload routine is called, so we must stop the PnP manager first. */ pnp_manager_stop(); wine_rb_destroy( &wine_drivers, unload_driver, NULL ); + + set_service_status( group_handle, SERVICE_STOPPED, 0 ); + CloseServiceHandle( manager_handle ); + CloseHandle( stop_event ); + return status; }
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0f5ab76a195..aa97dc60fec 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1685,4 +1685,4 @@ # All functions must be prefixed with '__wine_' (for internal functions) # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
-@ cdecl wine_ntoskrnl_main_loop(long) +@ cdecl wine_ntoskrnl_main_loop() diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index 3acc5e8a799..f1a30d3b447 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -25,120 +25,22 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" -#include "ddk/wdm.h" -#include "wine/svcctl.h" +#include "winsvc.h" #include "wine/debug.h" -#include "wine/heap.h"
-WINE_DEFAULT_DEBUG_CHANNEL(winedevice); +WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
-static const WCHAR servicesW[] = L"\Registry\Machine\System\CurrentControlSet\Services\"; - -extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ); +extern NTSTATUS CDECL wine_ntoskrnl_main_loop(void);
static WCHAR winedeviceW[] = L"winedevice"; -static SERVICE_STATUS_HANDLE service_handle; -static SC_HANDLE manager_handle; -static HANDLE stop_event; - -/* helper function to update service status */ -static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted ) -{ - SERVICE_STATUS status; - status.dwServiceType = SERVICE_WIN32; - status.dwCurrentState = state; - status.dwControlsAccepted = accepted; - status.dwWin32ExitCode = 0; - status.dwServiceSpecificExitCode = 0; - status.dwCheckPoint = 0; - status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0; - SetServiceStatus( handle, &status ); -} - -static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) -{ - UNICODE_STRING service_name; - DWORD result = NO_ERROR; - WCHAR *str; - - if (!(str = heap_alloc( sizeof(servicesW) + lstrlenW(driver_name)*sizeof(WCHAR) ))) - return STATUS_NO_MEMORY; - - lstrcpyW( str, servicesW ); - lstrcatW( str, driver_name ); - RtlInitUnicodeString( &service_name, str ); - - switch (ctrl) - { - case SERVICE_CONTROL_START: - result = RtlNtStatusToDosError(ZwLoadDriver( &service_name )); - break; - - case SERVICE_CONTROL_STOP: - result = RtlNtStatusToDosError(ZwUnloadDriver( &service_name )); - break; - - default: - FIXME( "got driver ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) ); - break; - } - - RtlFreeUnicodeString( &service_name ); - return result; -} - -static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context ) -{ - const WCHAR *service_group = context; - - if (ctrl & SERVICE_CONTROL_FORWARD_FLAG) - { - if (!event_data) return ERROR_INVALID_PARAMETER; - return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data ); - } - - switch (ctrl) - { - case SERVICE_CONTROL_STOP: - case SERVICE_CONTROL_SHUTDOWN: - TRACE( "shutting down %s\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_STOP_PENDING, 0 ); - SetEvent( stop_event ); - return NO_ERROR; - default: - FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_RUNNING, - SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); - return NO_ERROR; - } -}
static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { - WCHAR driver_dir[MAX_PATH]; const WCHAR *service_group = (argc >= 2) ? argv[1] : argv[0];
- if (!(stop_event = CreateEventW( NULL, TRUE, FALSE, NULL ))) - return; - if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT ))) - return; - if (!(service_handle = RegisterServiceCtrlHandlerExW( winedeviceW, service_handler, (void *)service_group ))) - return; - - GetSystemDirectoryW( driver_dir, MAX_PATH ); - wcscat( driver_dir, L"\drivers" ); - AddDllDirectory( driver_dir ); - TRACE( "starting service group %s\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_RUNNING, - SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ); - - wine_ntoskrnl_main_loop( stop_event ); - + wine_ntoskrnl_main_loop(); TRACE( "service group %s stopped\n", wine_dbgstr_w(service_group) ); - set_service_status( service_handle, SERVICE_STOPPED, 0 ); - CloseServiceHandle( manager_handle ); - CloseHandle( stop_event ); }
int __cdecl wmain( int argc, WCHAR *argv[] )