win-pvdrivers

view shutdownmon/shutdownmon.c @ 979:8f483a2b2991

Fix up PREfast warnings
author James Harper <james.harper@bendigoit.com.au>
date Sun Apr 15 19:47:10 2012 +1000 (2012-04-15)
parents 5bdb7251370c
children
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>
12 #include <powrprof.h>
13 #include <strsafe.h>
15 #define SERVICE_ID "ShutdownMon"
16 #define SERVICE_NAME "Xen Shutdown Monitor"
18 #define OLD_SERVICE_ID "XenShutdownMon"
20 DEFINE_GUID(GUID_XENBUS_IFACE, 0x14ce175a, 0x3ee2, 0x4fae, 0x92, 0x52, 0x0, 0xdb, 0xd8, 0x4f, 0x1, 0x8e);
22 enum xsd_sockmsg_type
23 {
24 XS_DEBUG,
25 XS_DIRECTORY,
26 XS_READ,
27 XS_GET_PERMS,
28 XS_WATCH,
29 XS_UNWATCH,
30 XS_TRANSACTION_START,
31 XS_TRANSACTION_END,
32 XS_INTRODUCE,
33 XS_RELEASE,
34 XS_GET_DOMAIN_PATH,
35 XS_WRITE,
36 XS_MKDIR,
37 XS_RM,
38 XS_SET_PERMS,
39 XS_WATCH_EVENT,
40 XS_ERROR,
41 XS_IS_DOMAIN_INTRODUCED,
42 XS_RESUME,
43 XS_SET_TARGET
44 };
46 struct xsd_sockmsg
47 {
48 ULONG type; /* XS_??? */
49 ULONG req_id;/* Request identifier, echoed in daemon's response. */
50 ULONG tx_id; /* Transaction id (0 if not related to a transaction). */
51 ULONG len; /* Length of data following this. */
53 /* Generally followed by nul-terminated string(s). */
54 };
55 SERVICE_STATUS service_status;
56 SERVICE_STATUS_HANDLE hStatus;
58 static void
59 install_service()
60 {
61 SC_HANDLE manager_handle;
62 SC_HANDLE service_handle;
63 TCHAR path[MAX_PATH];
64 TCHAR command_line[MAX_PATH + 10];
66 if(!GetModuleFileName(NULL, path, MAX_PATH))
67 {
68 printf("Cannot install service (%d)\n", GetLastError());
69 return;
70 }
72 StringCbPrintf(command_line, MAX_PATH + 10, "\"%s\" -s", path);
73 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
75 if (!manager_handle)
76 {
77 printf("OpenSCManager failed (%d)\n", GetLastError());
78 return;
79 }
81 service_handle = CreateService(
82 manager_handle, SERVICE_ID, SERVICE_NAME, SERVICE_ALL_ACCESS,
83 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
84 SERVICE_ERROR_NORMAL, command_line, NULL, NULL, NULL, NULL, NULL);
86 if (!service_handle)
87 {
88 printf("CreateService failed (%d)\n", GetLastError());
89 CloseServiceHandle(manager_handle);
90 return;
91 }
93 printf("Service installed\n");
95 CloseServiceHandle(service_handle);
96 CloseServiceHandle(manager_handle);
97 }
99 static void
100 remove_old_service()
101 {
102 SC_HANDLE manager_handle;
103 SC_HANDLE service_handle;
105 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
107 if (!manager_handle)
108 {
109 printf("OpenSCManager failed (%d)\n", GetLastError());
110 return;
111 }
113 service_handle = OpenService(manager_handle, OLD_SERVICE_ID, DELETE);
115 if (!service_handle)
116 {
117 printf("OpenService failed (%d)\n", GetLastError());
118 CloseServiceHandle(manager_handle);
119 return;
120 }
122 if (!DeleteService(service_handle))
123 {
124 printf("DeleteService failed (%d)\n", GetLastError());
125 CloseServiceHandle(service_handle);
126 CloseServiceHandle(manager_handle);
127 return;
128 }
130 printf("Old Service removed\n");
132 CloseServiceHandle(service_handle);
133 CloseServiceHandle(manager_handle);
134 }
136 static void
137 remove_service()
138 {
139 SC_HANDLE manager_handle;
140 SC_HANDLE service_handle;
142 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
144 if (!manager_handle)
145 {
146 printf("OpenSCManager failed (%d)\n", GetLastError());
147 return;
148 }
150 service_handle = OpenService(manager_handle, SERVICE_ID, DELETE);
152 if (!service_handle)
153 {
154 printf("OpenService failed (%d)\n", GetLastError());
155 CloseServiceHandle(manager_handle);
156 return;
157 }
159 if (!DeleteService(service_handle))
160 {
161 printf("DeleteService failed (%d)\n", GetLastError());
162 CloseServiceHandle(service_handle);
163 CloseServiceHandle(manager_handle);
164 return;
165 }
167 printf("Service removed\n");
169 CloseServiceHandle(service_handle);
170 CloseServiceHandle(manager_handle);
171 }
173 static void
174 do_hibernate()
175 {
176 HANDLE proc_handle = GetCurrentProcess();
177 TOKEN_PRIVILEGES *tp;
178 HANDLE token_handle;
180 printf("proc_handle = %p\n", proc_handle);
182 if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
183 {
184 printf("OpenProcessToken failed\n");
185 return;
186 }
187 printf("token_handle = %p\n", token_handle);
189 tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
190 if (!tp) {
191 printf("malloc failed\n");
192 CloseHandle(token_handle);
193 return;
194 }
195 tp->PrivilegeCount = 1;
196 if (!LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid)) {
197 printf("LookupPrivilegeValue failed\n");
198 free(tp);
199 CloseHandle(token_handle);
200 return;
201 }
203 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
204 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
205 {
206 printf("AdjustTokenPrivileges failed\n");
207 free(tp);
208 CloseHandle(token_handle);
209 return;
210 }
212 if (!SetSuspendState(TRUE, FALSE, FALSE)) {
213 printf("hibernate failed\n");
214 }
215 free(tp);
216 CloseHandle(token_handle);
217 }
219 static void
220 do_shutdown(BOOL bRebootAfterShutdown)
221 {
222 HANDLE proc_handle = GetCurrentProcess();
223 TOKEN_PRIVILEGES *tp;
224 HANDLE token_handle;
226 printf("proc_handle = %p\n", proc_handle);
228 if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
229 {
230 printf("OpenProcessToken failed\n");
231 return;
232 }
233 printf("token_handle = %p\n", token_handle);
235 tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
236 if (!tp) {
237 printf("malloc failed\n");
238 CloseHandle(token_handle);
239 return;
240 }
241 tp->PrivilegeCount = 1;
242 if (!LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
243 {
244 printf("LookupPrivilegeValue failed\n");
245 free(tp);
246 CloseHandle(token_handle);
247 return;
248 }
250 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
251 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
252 {
253 free(tp);
254 CloseHandle(token_handle);
255 return;
256 }
257 #pragma warning(suppress:28159)
258 if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, bRebootAfterShutdown, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
259 {
260 printf("InitiateSystemShutdownEx failed\n");
261 // Log a message to the system log here about a failed shutdown
262 }
263 printf("InitiateSystemShutdownEx succeeded\n");
265 free(tp);
266 CloseHandle(token_handle);
267 }
269 static char *
270 get_xen_interface_path()
271 {
272 HDEVINFO handle;
273 SP_DEVICE_INTERFACE_DATA sdid;
274 SP_DEVICE_INTERFACE_DETAIL_DATA *sdidd;
275 DWORD buf_len;
276 char *path;
278 handle = SetupDiGetClassDevs(&GUID_XENBUS_IFACE, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
279 if (handle == INVALID_HANDLE_VALUE)
280 {
281 printf("SetupDiGetClassDevs failed\n");
282 return NULL;
283 }
284 sdid.cbSize = sizeof(sdid);
285 if (!SetupDiEnumDeviceInterfaces(handle, NULL, &GUID_XENBUS_IFACE, 0, &sdid))
286 {
287 printf("SetupDiEnumDeviceInterfaces failed\n");
288 return NULL;
289 }
290 SetupDiGetDeviceInterfaceDetail(handle, &sdid, NULL, 0, &buf_len, NULL);
291 sdidd = malloc(buf_len);
292 sdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
293 if (!SetupDiGetDeviceInterfaceDetail(handle, &sdid, sdidd, buf_len, NULL, NULL))
294 {
295 printf("SetupDiGetDeviceInterfaceDetail failed\n");
296 return NULL;
297 }
299 path = malloc(strlen(sdidd->DevicePath) + 1);
300 StringCbCopyA(path, strlen(sdidd->DevicePath) + 1, sdidd->DevicePath);
301 free(sdidd);
303 return path;
304 }
306 static int
307 xb_add_watch(HANDLE handle, char *path)
308 {
309 char buf[1024];
310 struct xsd_sockmsg *msg;
311 DWORD bytes_written;
312 DWORD bytes_read;
313 char *token = "0";
315 msg = (struct xsd_sockmsg *)buf;
316 msg->type = XS_WATCH;
317 msg->req_id = 0;
318 msg->tx_id = 0;
319 msg->len = (ULONG)(strlen(path) + 1 + strlen(token) + 1);
320 StringCbCopyA(buf + sizeof(*msg), 1024 - sizeof(*msg), path);
321 StringCbCopyA(buf + sizeof(*msg) + strlen(path) + 1, 1024 - sizeof(*msg) - strlen(path) - 1, token);
323 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
324 {
325 printf("write failed\n");
326 return 0;
327 }
328 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
329 {
330 printf("read failed\n");
331 return 0;
332 }
333 printf("bytes_read = %d\n", bytes_read);
334 printf("msg->len = %d\n", msg->len);
335 buf[sizeof(*msg) + msg->len] = 0;
336 printf("msg text = %s\n", buf + sizeof(*msg));
338 return 1;
339 }
341 static int
342 xb_wait_event(HANDLE handle)
343 {
344 char buf[1024];
345 struct xsd_sockmsg *msg;
346 DWORD bytes_read;
348 printf("wait_event start\n");
349 msg = (struct xsd_sockmsg *)buf;
350 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
351 {
352 printf("read failed\n");
353 return 0;
354 }
355 printf("bytes_read = %d\n", bytes_read);
356 printf("msg->len = %d\n", msg->len);
357 buf[sizeof(*msg) + msg->len] = 0;
358 printf("msg text = %s\n", buf + sizeof(*msg));
359 return 1;
360 }
362 static char *
363 xb_read(HANDLE handle, char *path)
364 {
365 char buf[1024];
366 struct xsd_sockmsg *msg;
367 char *ret;
368 DWORD bytes_written;
369 DWORD bytes_read;
371 printf("read start\n");
372 msg = (struct xsd_sockmsg *)buf;
373 msg->type = XS_READ;
374 msg->req_id = 0;
375 msg->tx_id = 0;
376 msg->len = (ULONG)(strlen(path) + 1);
377 StringCbCopyA(buf + sizeof(*msg), 1024 - sizeof(*msg), path);
379 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
380 {
381 printf("write failed\n");
382 return NULL;
383 }
385 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
386 {
387 printf("read failed\n");
388 return NULL;
389 }
390 printf("bytes_read = %d\n", bytes_read);
391 printf("msg->len = %d\n", msg->len);
392 buf[sizeof(*msg) + msg->len] = 0;
393 printf("msg text = %s\n", buf + sizeof(*msg));
394 ret = malloc(strlen(buf + sizeof(*msg)) + 1);
395 StringCbCopyA(ret, 1024 - sizeof(*msg), buf + sizeof(*msg));
396 return ret;
397 }
399 static void
400 do_monitoring()
401 {
402 HANDLE handle;
403 int state;
404 char *path;
405 char *buf;
407 path = get_xen_interface_path();
408 if (path == NULL)
409 return;
411 handle = CreateFile(path, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
413 xb_add_watch(handle, "control/shutdown");
415 state = 0;
416 while(xb_wait_event(handle))
417 {
418 if (service_status.dwCurrentState != SERVICE_RUNNING)
419 return;
420 buf = xb_read(handle, "control/shutdown");
422 //printf("msg = '%s'\n", msg);
423 if (strcmp("poweroff", buf) == 0 || strcmp("halt", buf) == 0)
424 {
425 do_shutdown(FALSE);
426 }
427 else if (strcmp("reboot", buf) == 0)
428 {
429 do_shutdown(TRUE);
430 }
431 else if (strcmp("hibernate", buf) == 0)
432 {
433 do_hibernate();
434 }
435 }
436 }
438 void control_handler(DWORD request)
439 {
440 switch(request)
441 {
442 case SERVICE_CONTROL_STOP:
443 service_status.dwWin32ExitCode = 0;
444 service_status.dwCurrentState = SERVICE_STOPPED;
445 SetServiceStatus (hStatus, &service_status);
446 return;
448 case SERVICE_CONTROL_SHUTDOWN:
449 service_status.dwWin32ExitCode = 0;
450 service_status.dwCurrentState = SERVICE_STOPPED;
451 SetServiceStatus (hStatus, &service_status);
452 return;
454 default:
455 break;
456 }
458 SetServiceStatus (hStatus, &service_status);
460 return;
461 }
463 void service_main(int argc, char *argv[])
464 {
465 UNREFERENCED_PARAMETER (argc);
466 UNREFERENCED_PARAMETER (argv);
468 printf("Entering service_main\n");
470 service_status.dwServiceType = SERVICE_WIN32;
471 service_status.dwCurrentState = SERVICE_START_PENDING;
472 service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
473 service_status.dwWin32ExitCode = 0;
474 service_status.dwServiceSpecificExitCode = 0;
475 service_status.dwCheckPoint = 0;
476 service_status.dwWaitHint = 0;
478 hStatus = RegisterServiceCtrlHandler(SERVICE_ID, (LPHANDLER_FUNCTION)control_handler);
479 if (hStatus == (SERVICE_STATUS_HANDLE)0)
480 {
481 printf("RegisterServiceCtrlHandler failed\n");
482 return;
483 }
485 service_status.dwCurrentState = SERVICE_RUNNING;
486 SetServiceStatus(hStatus, &service_status);
488 do_monitoring();
490 printf("All done\n");
492 return;
493 }
496 static void
497 print_usage(char *name)
498 {
499 printf("Usage:\n");
500 printf(" %s <options>\n", name);
501 printf("\n");
502 printf("Options:\n");
503 printf(" -d run in foreground\n");
504 printf(" -s run as service\n");
505 printf(" -i install service\n");
506 printf(" -u uninstall service\n");
507 printf(" -o remove the old .NET service\n");
508 }
510 int __cdecl
511 main(
512 __in ULONG argc,
513 __in_ecount(argc) PCHAR argv[]
514 )
515 {
516 SERVICE_TABLE_ENTRY service_table[2];
518 if (argc == 0)
519 {
520 print_usage("shutdownmon");
521 return 1;
522 }
523 if (argc != 2 || (argc == 2 && (strlen(argv[1]) != 2 || argv[1][0] != '-')))
524 {
525 print_usage(argv[0]);
526 return 1;
527 }
529 switch(argv[1][1])
530 {
531 case 'd':
532 service_status.dwCurrentState = SERVICE_RUNNING;
533 do_monitoring();
534 break;
535 case 's':
536 service_table[0].lpServiceName = SERVICE_ID;
537 service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
539 service_table[1].lpServiceName = NULL;
540 service_table[1].lpServiceProc = NULL;
542 StartServiceCtrlDispatcher(service_table);
543 break;
544 case 'i':
545 install_service();
546 break;
547 case 'u':
548 remove_service();
549 break;
550 case 'o':
551 remove_old_service();
552 break;
553 default:
554 print_usage(argv[0]);
555 return 1;
556 }
557 return 0;
558 }