winmm: Use wide-char string literals.
[wine.git] / programs / winedevice / device.c
blobc591d7433378942e7b9859ac8e05c7f31e7ca260
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 <stdarg.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winternl.h"
28 #include "ddk/wdm.h"
29 #include "wine/svcctl.h"
30 #include "wine/debug.h"
31 #include "wine/heap.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(winedevice);
35 static const WCHAR servicesW[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
37 extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event );
39 static WCHAR winedeviceW[] = L"winedevice";
40 static SERVICE_STATUS_HANDLE service_handle;
41 static SC_HANDLE manager_handle;
42 static HANDLE stop_event;
44 /* helper function to update service status */
45 static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted )
47 SERVICE_STATUS status;
48 status.dwServiceType = SERVICE_WIN32;
49 status.dwCurrentState = state;
50 status.dwControlsAccepted = accepted;
51 status.dwWin32ExitCode = 0;
52 status.dwServiceSpecificExitCode = 0;
53 status.dwCheckPoint = 0;
54 status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0;
55 SetServiceStatus( handle, &status );
58 static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name )
60 UNICODE_STRING service_name;
61 DWORD result = NO_ERROR;
62 WCHAR *str;
64 if (!(str = heap_alloc( sizeof(servicesW) + lstrlenW(driver_name)*sizeof(WCHAR) )))
65 return STATUS_NO_MEMORY;
67 lstrcpyW( str, servicesW );
68 lstrcatW( str, driver_name );
69 RtlInitUnicodeString( &service_name, str );
71 switch (ctrl)
73 case SERVICE_CONTROL_START:
74 result = RtlNtStatusToDosError(ZwLoadDriver( &service_name ));
75 break;
77 case SERVICE_CONTROL_STOP:
78 result = RtlNtStatusToDosError(ZwUnloadDriver( &service_name ));
79 break;
81 default:
82 FIXME( "got driver ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) );
83 break;
86 RtlFreeUnicodeString( &service_name );
87 return result;
90 static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
92 const WCHAR *service_group = context;
94 if (ctrl & SERVICE_CONTROL_FORWARD_FLAG)
96 if (!event_data) return ERROR_INVALID_PARAMETER;
97 return device_handler( ctrl & ~SERVICE_CONTROL_FORWARD_FLAG, (const WCHAR *)event_data );
100 switch (ctrl)
102 case SERVICE_CONTROL_STOP:
103 case SERVICE_CONTROL_SHUTDOWN:
104 TRACE( "shutting down %s\n", wine_dbgstr_w(service_group) );
105 set_service_status( service_handle, SERVICE_STOP_PENDING, 0 );
106 SetEvent( stop_event );
107 return NO_ERROR;
108 default:
109 FIXME( "got service ctrl %x for %s\n", ctrl, wine_dbgstr_w(service_group) );
110 set_service_status( service_handle, SERVICE_RUNNING,
111 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
112 return NO_ERROR;
116 static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
118 const WCHAR *service_group = (argc >= 2) ? argv[1] : argv[0];
120 if (!(stop_event = CreateEventW( NULL, TRUE, FALSE, NULL )))
121 return;
122 if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
123 return;
124 if (!(service_handle = RegisterServiceCtrlHandlerExW( winedeviceW, service_handler, (void *)service_group )))
125 return;
127 TRACE( "starting service group %s\n", wine_dbgstr_w(service_group) );
128 set_service_status( service_handle, SERVICE_RUNNING,
129 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
131 wine_ntoskrnl_main_loop( stop_event );
133 TRACE( "service group %s stopped\n", wine_dbgstr_w(service_group) );
134 set_service_status( service_handle, SERVICE_STOPPED, 0 );
135 CloseServiceHandle( manager_handle );
136 CloseHandle( stop_event );
139 int __cdecl wmain( int argc, WCHAR *argv[] )
141 SERVICE_TABLE_ENTRYW service_table[2];
143 service_table[0].lpServiceName = winedeviceW;
144 service_table[0].lpServiceProc = ServiceMain;
145 service_table[1].lpServiceName = NULL;
146 service_table[1].lpServiceProc = NULL;
148 StartServiceCtrlDispatcherW( service_table );
149 return 0;