[PATCH 2/8] winedevice: Move service_handler() to ntoskrnl.

Zebediah Figura z.figura12 at gmail.com
Wed Mar 31 11:16:32 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at 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[] )
-- 
2.30.2




More information about the wine-devel mailing list