win-pvdrivers

view shutdownmon/shutdownmon.c @ 592:d1754b0e1ead

Start of support for PNP OID's
author James Harper <james.harper@bendigoit.com.au>
date Fri Jun 19 22:15:47 2009 +1000 (2009-06-19)
parents 47fae39bc373
children b79b67b46d0c
line source
1 #pragma warning(disable: 4201)
2 #include <windows.h>
3 #include <basetyps.h>
4 #include <stdlib.h>
5 #include <wtypes.h>
6 #include <initguid.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <winioctl.h>
10 #include <setupapi.h>
11 #include <ctype.h>
13 #define SERVICE_ID "ShutdownMon"
14 #define SERVICE_NAME "Xen Shutdown Monitor"
16 #define OLD_SERVICE_ID "XenShutdownMon"
18 DEFINE_GUID(GUID_XENBUS_IFACE, 0x14ce175a, 0x3ee2, 0x4fae, 0x92, 0x52, 0x0, 0xdb, 0xd8, 0x4f, 0x1, 0x8e);
20 enum xsd_sockmsg_type
21 {
22 XS_DEBUG,
23 XS_DIRECTORY,
24 XS_READ,
25 XS_GET_PERMS,
26 XS_WATCH,
27 XS_UNWATCH,
28 XS_TRANSACTION_START,
29 XS_TRANSACTION_END,
30 XS_INTRODUCE,
31 XS_RELEASE,
32 XS_GET_DOMAIN_PATH,
33 XS_WRITE,
34 XS_MKDIR,
35 XS_RM,
36 XS_SET_PERMS,
37 XS_WATCH_EVENT,
38 XS_ERROR,
39 XS_IS_DOMAIN_INTRODUCED,
40 XS_RESUME,
41 XS_SET_TARGET
42 };
44 struct xsd_sockmsg
45 {
46 ULONG type; /* XS_??? */
47 ULONG req_id;/* Request identifier, echoed in daemon's response. */
48 ULONG tx_id; /* Transaction id (0 if not related to a transaction). */
49 ULONG len; /* Length of data following this. */
51 /* Generally followed by nul-terminated string(s). */
52 };
53 SERVICE_STATUS service_status;
54 SERVICE_STATUS_HANDLE hStatus;
56 static void
57 install_service()
58 {
59 SC_HANDLE manager_handle;
60 SC_HANDLE service_handle;
61 TCHAR path[MAX_PATH];
62 TCHAR command_line[MAX_PATH + 10];
64 if(!GetModuleFileName(NULL, path, MAX_PATH))
65 {
66 printf("Cannot install service (%d)\n", GetLastError());
67 return;
68 }
70 sprintf(command_line, "\"%s\" -s", path);
71 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
73 if (!manager_handle)
74 {
75 printf("OpenSCManager failed (%d)\n", GetLastError());
76 return;
77 }
79 service_handle = CreateService(
80 manager_handle, SERVICE_ID, SERVICE_NAME, SERVICE_ALL_ACCESS,
81 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
82 SERVICE_ERROR_NORMAL, command_line, NULL, NULL, NULL, NULL, NULL);
84 if (!service_handle)
85 {
86 printf("CreateService failed (%d)\n", GetLastError());
87 CloseServiceHandle(manager_handle);
88 return;
89 }
91 printf("Service installed\n");
93 CloseServiceHandle(service_handle);
94 CloseServiceHandle(manager_handle);
95 }
97 static void
98 remove_old_service()
99 {
100 SC_HANDLE manager_handle;
101 SC_HANDLE service_handle;
103 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
105 if (!manager_handle)
106 {
107 printf("OpenSCManager failed (%d)\n", GetLastError());
108 return;
109 }
111 service_handle = OpenService(manager_handle, OLD_SERVICE_ID, DELETE);
113 if (!service_handle)
114 {
115 printf("OpenService failed (%d)\n", GetLastError());
116 CloseServiceHandle(manager_handle);
117 return;
118 }
120 if (!DeleteService(service_handle))
121 {
122 printf("DeleteService failed (%d)\n", GetLastError());
123 CloseServiceHandle(service_handle);
124 CloseServiceHandle(manager_handle);
125 return;
126 }
128 printf("Old Service removed\n");
130 CloseServiceHandle(service_handle);
131 CloseServiceHandle(manager_handle);
132 }
134 static void
135 remove_service()
136 {
137 SC_HANDLE manager_handle;
138 SC_HANDLE service_handle;
140 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
142 if (!manager_handle)
143 {
144 printf("OpenSCManager failed (%d)\n", GetLastError());
145 return;
146 }
148 service_handle = OpenService(manager_handle, SERVICE_ID, DELETE);
150 if (!service_handle)
151 {
152 printf("OpenService failed (%d)\n", GetLastError());
153 CloseServiceHandle(manager_handle);
154 return;
155 }
157 if (!DeleteService(service_handle))
158 {
159 printf("DeleteService failed (%d)\n", GetLastError());
160 CloseServiceHandle(service_handle);
161 CloseServiceHandle(manager_handle);
162 return;
163 }
165 printf("Service removed\n");
167 CloseServiceHandle(service_handle);
168 CloseServiceHandle(manager_handle);
169 }
171 static void
172 do_shutdown(BOOL bRebootAfterShutdown)
173 {
174 HANDLE proc_handle = GetCurrentProcess();
175 TOKEN_PRIVILEGES *tp;
176 HANDLE token_handle;
178 printf("proc_handle = %p\n", proc_handle);
180 if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
181 {
182 printf("OpenProcessToken failed\n");
183 return;
184 }
185 printf("token_handle = %p\n", token_handle);
187 tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
188 tp->PrivilegeCount = 1;
189 if (!LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
190 {
191 printf("LookupPrivilegeValue failed\n");
192 CloseHandle(token_handle);
193 return;
194 }
196 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
197 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
198 {
199 CloseHandle(token_handle);
200 return;
201 }
203 if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, bRebootAfterShutdown, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
204 {
205 printf("InitiateSystemShutdownEx failed\n");
206 // Log a message to the system log here about a failed shutdown
207 }
208 printf("InitiateSystemShutdownEx succeeded\n");
210 CloseHandle(token_handle);
211 }
213 static char *
214 get_xen_interface_path()
215 {
216 HDEVINFO handle;
217 SP_DEVICE_INTERFACE_DATA sdid;
218 SP_DEVICE_INTERFACE_DETAIL_DATA *sdidd;
219 DWORD buf_len;
220 char *path;
222 handle = SetupDiGetClassDevs(&GUID_XENBUS_IFACE, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
223 if (handle == INVALID_HANDLE_VALUE)
224 {
225 printf("SetupDiGetClassDevs failed\n");
226 return NULL;
227 }
228 sdid.cbSize = sizeof(sdid);
229 if (!SetupDiEnumDeviceInterfaces(handle, NULL, &GUID_XENBUS_IFACE, 0, &sdid))
230 {
231 printf("SetupDiEnumDeviceInterfaces failed\n");
232 return NULL;
233 }
234 SetupDiGetDeviceInterfaceDetail(handle, &sdid, NULL, 0, &buf_len, NULL);
235 sdidd = malloc(buf_len);
236 sdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
237 if (!SetupDiGetDeviceInterfaceDetail(handle, &sdid, sdidd, buf_len, NULL, NULL))
238 {
239 printf("SetupDiGetDeviceInterfaceDetail failed\n");
240 return NULL;
241 }
243 path = malloc(strlen(sdidd->DevicePath) + 1);
244 strcpy(path, sdidd->DevicePath);
245 free(sdidd);
247 return path;
248 }
250 static int
251 xb_add_watch(HANDLE handle, char *path)
252 {
253 char buf[1024];
254 struct xsd_sockmsg *msg;
255 DWORD bytes_written;
256 DWORD bytes_read;
257 char *token = "0";
259 msg = (struct xsd_sockmsg *)buf;
260 msg->type = XS_WATCH;
261 msg->req_id = 0;
262 msg->tx_id = 0;
263 msg->len = (ULONG)(strlen(path) + 1 + strlen(token) + 1);
264 strcpy(buf + sizeof(*msg), path);
265 strcpy(buf + sizeof(*msg) + strlen(path) + 1, token);
267 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
268 {
269 printf("write failed\n");
270 return 0;
271 }
272 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
273 {
274 printf("read failed\n");
275 return 0;
276 }
277 printf("bytes_read = %d\n", bytes_read);
278 printf("msg->len = %d\n", msg->len);
279 buf[sizeof(*msg) + msg->len] = 0;
280 printf("msg text = %s\n", buf + sizeof(*msg));
282 return 1;
283 }
285 static int
286 xb_wait_event(HANDLE handle)
287 {
288 char buf[1024];
289 struct xsd_sockmsg *msg;
290 DWORD bytes_read;
292 printf("wait_event start\n");
293 msg = (struct xsd_sockmsg *)buf;
294 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
295 {
296 printf("read failed\n");
297 return 0;
298 }
299 printf("bytes_read = %d\n", bytes_read);
300 printf("msg->len = %d\n", msg->len);
301 buf[sizeof(*msg) + msg->len] = 0;
302 printf("msg text = %s\n", buf + sizeof(*msg));
303 return 1;
304 }
306 static char *
307 xb_read(HANDLE handle, char *path)
308 {
309 char buf[1024];
310 struct xsd_sockmsg *msg;
311 char *ret;
312 DWORD bytes_written;
313 DWORD bytes_read;
315 printf("read start\n");
316 msg = (struct xsd_sockmsg *)buf;
317 msg->type = XS_READ;
318 msg->req_id = 0;
319 msg->tx_id = 0;
320 msg->len = (ULONG)(strlen(path) + 1);
321 strcpy(buf + sizeof(*msg), path);
323 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
324 {
325 printf("write failed\n");
326 return NULL;
327 }
329 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
330 {
331 printf("read failed\n");
332 return NULL;
333 }
334 printf("bytes_read = %d\n", bytes_read);
335 printf("msg->len = %d\n", msg->len);
336 buf[sizeof(*msg) + msg->len] = 0;
337 printf("msg text = %s\n", buf + sizeof(*msg));
338 ret = malloc(strlen(buf + sizeof(*msg)) + 1);
339 strcpy(ret, buf + sizeof(*msg));
340 return ret;
341 }
343 static void
344 do_monitoring()
345 {
346 HANDLE handle;
347 int state;
348 char *path;
349 char *buf;
351 path = get_xen_interface_path();
352 if (path == NULL)
353 return;
355 handle = CreateFile(path, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
357 xb_add_watch(handle, "control/shutdown");
359 state = 0;
360 while(xb_wait_event(handle))
361 {
362 if (service_status.dwCurrentState != SERVICE_RUNNING)
363 return;
364 buf = xb_read(handle, "control/shutdown");
366 //printf("msg = '%s'\n", msg);
367 if (strcmp("poweroff", buf) == 0 || strcmp("halt", buf) == 0)
368 {
369 do_shutdown(FALSE);
370 }
371 else if (strcmp("reboot", buf) == 0)
372 {
373 do_shutdown(TRUE);
374 }
375 }
376 }
378 void control_handler(DWORD request)
379 {
380 switch(request)
381 {
382 case SERVICE_CONTROL_STOP:
383 service_status.dwWin32ExitCode = 0;
384 service_status.dwCurrentState = SERVICE_STOPPED;
385 SetServiceStatus (hStatus, &service_status);
386 return;
388 case SERVICE_CONTROL_SHUTDOWN:
389 service_status.dwWin32ExitCode = 0;
390 service_status.dwCurrentState = SERVICE_STOPPED;
391 SetServiceStatus (hStatus, &service_status);
392 return;
394 default:
395 break;
396 }
398 SetServiceStatus (hStatus, &service_status);
400 return;
401 }
403 void service_main(int argc, char *argv[])
404 {
405 UNREFERENCED_PARAMETER (argc);
406 UNREFERENCED_PARAMETER (argv);
408 printf("Entering service_main\n");
410 service_status.dwServiceType = SERVICE_WIN32;
411 service_status.dwCurrentState = SERVICE_START_PENDING;
412 service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
413 service_status.dwWin32ExitCode = 0;
414 service_status.dwServiceSpecificExitCode = 0;
415 service_status.dwCheckPoint = 0;
416 service_status.dwWaitHint = 0;
418 hStatus = RegisterServiceCtrlHandler(SERVICE_ID, (LPHANDLER_FUNCTION)control_handler);
419 if (hStatus == (SERVICE_STATUS_HANDLE)0)
420 {
421 printf("RegisterServiceCtrlHandler failed\n");
422 return;
423 }
425 service_status.dwCurrentState = SERVICE_RUNNING;
426 SetServiceStatus(hStatus, &service_status);
428 do_monitoring();
430 printf("All done\n");
432 return;
433 }
436 static void
437 print_usage(char *name)
438 {
439 printf("Usage:\n");
440 printf(" %s <options>\n", name);
441 printf("\n");
442 printf("Options:\n");
443 printf(" -d run in foreground\n");
444 printf(" -s run as service\n");
445 printf(" -i install service\n");
446 printf(" -u uninstall service\n");
447 printf(" -o remove the old .NET service\n");
448 }
450 int __cdecl
451 main(
452 __in ULONG argc,
453 __in_ecount(argc) PCHAR argv[]
454 )
455 {
456 SERVICE_TABLE_ENTRY service_table[2];
458 if (argc == 0)
459 {
460 print_usage("shutdownmon");
461 return 1;
462 }
463 if (argc != 2 || (argc == 2 && (strlen(argv[1]) != 2 || argv[1][0] != '-')))
464 {
465 print_usage(argv[0]);
466 return 1;
467 }
469 switch(argv[1][1])
470 {
471 case 'd':
472 service_status.dwCurrentState = SERVICE_RUNNING;
473 do_monitoring();
474 break;
475 case 's':
476 service_table[0].lpServiceName = SERVICE_ID;
477 service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
479 service_table[1].lpServiceName = NULL;
480 service_table[1].lpServiceProc = NULL;
482 StartServiceCtrlDispatcher(service_table);
483 break;
484 case 'i':
485 install_service();
486 break;
487 case 'u':
488 remove_service();
489 break;
490 case 'o':
491 remove_old_service();
492 break;
493 default:
494 print_usage(argv[0]);
495 return 1;
496 }
497 return 0;
498 }