[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