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
23 #include "wine/port.h"
28 #define WIN32_NO_STATUS
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',
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
;
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
);
82 case SERVICE_CONTROL_START
:
83 result
= RtlNtStatusToDosError(ZwLoadDriver( &service_name
));
86 case SERVICE_CONTROL_STOP
:
87 result
= RtlNtStatusToDosError(ZwUnloadDriver( &service_name
));
91 FIXME( "got driver ctrl %x for %s\n", ctrl
, wine_dbgstr_w(driver_name
) );
95 RtlFreeUnicodeString( &service_name
);
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
);
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
);
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
);
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
)))
131 if (!(manager_handle
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_CONNECT
)))
133 if (!(service_handle
= RegisterServiceCtrlHandlerExW( winedeviceW
, service_handler
, (void *)service_group
)))
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
);