ntdll: Translate signal to trap when trap code is 0 on ARM.
[wine.git] / programs / winedevice / device.c
blob201a0411d60d02101ef5d8e9a7d979eafdde3e9b
1 /*
2 * Service process to load a kernel driver
4 * Copyright 2007 Alexandre Julliard
5 * Copyright 2016 Sebastian Lackner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #include "windef.h"
30 #include "winternl.h"
31 #include "ddk/wdm.h"
32 #include "wine/svcctl.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(winedevice);
39 static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
40 '\\','M','a','c','h','i','n','e',
41 '\\','S','y','s','t','e','m',
42 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
43 '\\','S','e','r','v','i','c','e','s',
44 '\\',0};
46 extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event );
48 static const WCHAR winedeviceW[] = {'w','i','n','e','d','e','v','i','c','e',0};
49 static SERVICE_STATUS_HANDLE service_handle;
50 static SC_HANDLE manager_handle;
51 static HANDLE stop_event;
53 /* helper function to update service status */
54 static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted )
56 SERVICE_STATUS status;
57 status.dwServiceType = SERVICE_WIN32;
58 status.dwCurrentState = state;
59 status.dwControlsAccepted = accepted;
60 status.dwWin32ExitCode = 0;
61 status.dwServiceSpecificExitCode = 0;
62 status.dwCheckPoint = 0;
63 status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0;
64 SetServiceStatus( handle, &status );
67 static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name )
69 UNICODE_STRING service_name;
70 DWORD result = NO_ERROR;
71 WCHAR *str;
73 if (!(str = heap_alloc( sizeof(servicesW) + strlenW(driver_name)*sizeof(WCHAR) )))
74 return STATUS_NO_MEMORY;
76 lstrcpyW( str, servicesW );
77 lstrcatW( str, driver_name );
78 RtlInitUnicodeString( &service_name, str );
80 switch (ctrl)
82 case SERVICE_CONTROL_START:
83 result = RtlNtStatusToDosError(ZwLoadDriver( &service_name ));
84 break;
86 case SERVICE_CONTROL_STOP:
87 result = RtlNtStatusToDosError(ZwUnloadDriver( &service_name ));
88 break;
90 default:
91 FIXME( "got driver ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) );
92 break;
95 RtlFreeUnicodeString( &service_name );
96 return result;
99 static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
101 const WCHAR *service_group = context;
103 if (ctrl & SERVICE_CONTROL_FORWARD_FLAG)
105 if (!event_data) return ERROR_INVALID_PARAMETER;
106 return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data );
109 switch (ctrl)
111 case SERVICE_CONTROL_STOP:
112 case SERVICE_CONTROL_SHUTDOWN:
113 TRACE( "shutting down %s\n", wine_dbgstr_w(service_group) );
114 set_service_status( service_handle, SERVICE_STOP_PENDING, 0 );
115 SetEvent( stop_event );
116 return NO_ERROR;
117 default:
118 FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(service_group) );
119 set_service_status( service_handle, SERVICE_RUNNING,
120 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
121 return NO_ERROR;
125 static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
127 const WCHAR *service_group = (argc >= 2) ? argv[1] : argv[0];
129 if (!(stop_event = CreateEventW( NULL, TRUE, FALSE, NULL )))
130 return;
131 if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
132 return;
133 if (!(service_handle = RegisterServiceCtrlHandlerExW( winedeviceW, service_handler, (void *)service_group )))
134 return;
136 TRACE( "starting service group %s\n", wine_dbgstr_w(service_group) );
137 set_service_status( service_handle, SERVICE_RUNNING,
138 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
140 wine_ntoskrnl_main_loop( stop_event );
142 TRACE( "service group %s stopped\n", wine_dbgstr_w(service_group) );
143 set_service_status( service_handle, SERVICE_STOPPED, 0 );
144 CloseServiceHandle( manager_handle );
145 CloseHandle( stop_event );
148 int wmain( int argc, WCHAR *argv[] )
150 SERVICE_TABLE_ENTRYW service_table[2];
152 service_table[0].lpServiceName = (void *)winedeviceW;
153 service_table[0].lpServiceProc = ServiceMain;
154 service_table[1].lpServiceName = NULL;
155 service_table[1].lpServiceProc = NULL;
157 StartServiceCtrlDispatcherW( service_table );
158 return 0;