win-pvdrivers

view shutdownmon/shutdownmon.c @ 716:5bdb7251370c

Use WinDDK 7600.16385.0
Update userspace binaries to build for XP not 2K (2K not supported in new DDK)
Fix lots of PREfast errors
Make build and installer less dependant on DDK version
Fix IRQL crash in DpgPrint hooking
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 22 22:44:07 2009 +1100 (2009-12-22)
parents b79b67b46d0c
children 8f483a2b2991
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 tp->PrivilegeCount = 1;
191 if (!LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
192 {
193 printf("LookupPrivilegeValue failed\n");
194 CloseHandle(token_handle);
195 return;
196 }
198 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
199 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
200 {
201 CloseHandle(token_handle);
202 return;
203 }
205 if (!SetSuspendState(TRUE, FALSE, FALSE))
206 {
207 printf("hibernate failed\n");
208 }
210 CloseHandle(token_handle);
211 }
213 static void
214 do_shutdown(BOOL bRebootAfterShutdown)
215 {
216 HANDLE proc_handle = GetCurrentProcess();
217 TOKEN_PRIVILEGES *tp;
218 HANDLE token_handle;
220 printf("proc_handle = %p\n", proc_handle);
222 if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
223 {
224 printf("OpenProcessToken failed\n");
225 return;
226 }
227 printf("token_handle = %p\n", token_handle);
229 tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
230 tp->PrivilegeCount = 1;
231 if (!LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
232 {
233 printf("LookupPrivilegeValue failed\n");
234 CloseHandle(token_handle);
235 return;
236 }
238 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
239 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
240 {
241 CloseHandle(token_handle);
242 return;
243 }
245 if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, bRebootAfterShutdown, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
246 {
247 printf("InitiateSystemShutdownEx failed\n");
248 // Log a message to the system log here about a failed shutdown
249 }
250 printf("InitiateSystemShutdownEx succeeded\n");
252 CloseHandle(token_handle);
253 }
255 static char *
256 get_xen_interface_path()
257 {
258 HDEVINFO handle;
259 SP_DEVICE_INTERFACE_DATA sdid;
260 SP_DEVICE_INTERFACE_DETAIL_DATA *sdidd;
261 DWORD buf_len;
262 char *path;
264 handle = SetupDiGetClassDevs(&GUID_XENBUS_IFACE, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
265 if (handle == INVALID_HANDLE_VALUE)
266 {
267 printf("SetupDiGetClassDevs failed\n");
268 return NULL;
269 }
270 sdid.cbSize = sizeof(sdid);
271 if (!SetupDiEnumDeviceInterfaces(handle, NULL, &GUID_XENBUS_IFACE, 0, &sdid))
272 {
273 printf("SetupDiEnumDeviceInterfaces failed\n");
274 return NULL;
275 }
276 SetupDiGetDeviceInterfaceDetail(handle, &sdid, NULL, 0, &buf_len, NULL);
277 sdidd = malloc(buf_len);
278 sdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
279 if (!SetupDiGetDeviceInterfaceDetail(handle, &sdid, sdidd, buf_len, NULL, NULL))
280 {
281 printf("SetupDiGetDeviceInterfaceDetail failed\n");
282 return NULL;
283 }
285 path = malloc(strlen(sdidd->DevicePath) + 1);
286 StringCbCopyA(path, strlen(sdidd->DevicePath) + 1, sdidd->DevicePath);
287 free(sdidd);
289 return path;
290 }
292 static int
293 xb_add_watch(HANDLE handle, char *path)
294 {
295 char buf[1024];
296 struct xsd_sockmsg *msg;
297 DWORD bytes_written;
298 DWORD bytes_read;
299 char *token = "0";
301 msg = (struct xsd_sockmsg *)buf;
302 msg->type = XS_WATCH;
303 msg->req_id = 0;
304 msg->tx_id = 0;
305 msg->len = (ULONG)(strlen(path) + 1 + strlen(token) + 1);
306 StringCbCopyA(buf + sizeof(*msg), 1024 - sizeof(*msg), path);
307 StringCbCopyA(buf + sizeof(*msg) + strlen(path) + 1, 1024 - sizeof(*msg) - strlen(path) - 1, token);
309 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
310 {
311 printf("write failed\n");
312 return 0;
313 }
314 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
315 {
316 printf("read failed\n");
317 return 0;
318 }
319 printf("bytes_read = %d\n", bytes_read);
320 printf("msg->len = %d\n", msg->len);
321 buf[sizeof(*msg) + msg->len] = 0;
322 printf("msg text = %s\n", buf + sizeof(*msg));
324 return 1;
325 }
327 static int
328 xb_wait_event(HANDLE handle)
329 {
330 char buf[1024];
331 struct xsd_sockmsg *msg;
332 DWORD bytes_read;
334 printf("wait_event start\n");
335 msg = (struct xsd_sockmsg *)buf;
336 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
337 {
338 printf("read failed\n");
339 return 0;
340 }
341 printf("bytes_read = %d\n", bytes_read);
342 printf("msg->len = %d\n", msg->len);
343 buf[sizeof(*msg) + msg->len] = 0;
344 printf("msg text = %s\n", buf + sizeof(*msg));
345 return 1;
346 }
348 static char *
349 xb_read(HANDLE handle, char *path)
350 {
351 char buf[1024];
352 struct xsd_sockmsg *msg;
353 char *ret;
354 DWORD bytes_written;
355 DWORD bytes_read;
357 printf("read start\n");
358 msg = (struct xsd_sockmsg *)buf;
359 msg->type = XS_READ;
360 msg->req_id = 0;
361 msg->tx_id = 0;
362 msg->len = (ULONG)(strlen(path) + 1);
363 StringCbCopyA(buf + sizeof(*msg), 1024 - sizeof(*msg), path);
365 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
366 {
367 printf("write failed\n");
368 return NULL;
369 }
371 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
372 {
373 printf("read failed\n");
374 return NULL;
375 }
376 printf("bytes_read = %d\n", bytes_read);
377 printf("msg->len = %d\n", msg->len);
378 buf[sizeof(*msg) + msg->len] = 0;
379 printf("msg text = %s\n", buf + sizeof(*msg));
380 ret = malloc(strlen(buf + sizeof(*msg)) + 1);
381 StringCbCopyA(ret, 1024 - sizeof(*msg), buf + sizeof(*msg));
382 return ret;
383 }
385 static void
386 do_monitoring()
387 {
388 HANDLE handle;
389 int state;
390 char *path;
391 char *buf;
393 path = get_xen_interface_path();
394 if (path == NULL)
395 return;
397 handle = CreateFile(path, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
399 xb_add_watch(handle, "control/shutdown");
401 state = 0;
402 while(xb_wait_event(handle))
403 {
404 if (service_status.dwCurrentState != SERVICE_RUNNING)
405 return;
406 buf = xb_read(handle, "control/shutdown");
408 //printf("msg = '%s'\n", msg);
409 if (strcmp("poweroff", buf) == 0 || strcmp("halt", buf) == 0)
410 {
411 do_shutdown(FALSE);
412 }
413 else if (strcmp("reboot", buf) == 0)
414 {
415 do_shutdown(TRUE);
416 }
417 else if (strcmp("hibernate", buf) == 0)
418 {
419 do_hibernate();
420 }
421 }
422 }
424 void control_handler(DWORD request)
425 {
426 switch(request)
427 {
428 case SERVICE_CONTROL_STOP:
429 service_status.dwWin32ExitCode = 0;
430 service_status.dwCurrentState = SERVICE_STOPPED;
431 SetServiceStatus (hStatus, &service_status);
432 return;
434 case SERVICE_CONTROL_SHUTDOWN:
435 service_status.dwWin32ExitCode = 0;
436 service_status.dwCurrentState = SERVICE_STOPPED;
437 SetServiceStatus (hStatus, &service_status);
438 return;
440 default:
441 break;
442 }
444 SetServiceStatus (hStatus, &service_status);
446 return;
447 }
449 void service_main(int argc, char *argv[])
450 {
451 UNREFERENCED_PARAMETER (argc);
452 UNREFERENCED_PARAMETER (argv);
454 printf("Entering service_main\n");
456 service_status.dwServiceType = SERVICE_WIN32;
457 service_status.dwCurrentState = SERVICE_START_PENDING;
458 service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
459 service_status.dwWin32ExitCode = 0;
460 service_status.dwServiceSpecificExitCode = 0;
461 service_status.dwCheckPoint = 0;
462 service_status.dwWaitHint = 0;
464 hStatus = RegisterServiceCtrlHandler(SERVICE_ID, (LPHANDLER_FUNCTION)control_handler);
465 if (hStatus == (SERVICE_STATUS_HANDLE)0)
466 {
467 printf("RegisterServiceCtrlHandler failed\n");
468 return;
469 }
471 service_status.dwCurrentState = SERVICE_RUNNING;
472 SetServiceStatus(hStatus, &service_status);
474 do_monitoring();
476 printf("All done\n");
478 return;
479 }
482 static void
483 print_usage(char *name)
484 {
485 printf("Usage:\n");
486 printf(" %s <options>\n", name);
487 printf("\n");
488 printf("Options:\n");
489 printf(" -d run in foreground\n");
490 printf(" -s run as service\n");
491 printf(" -i install service\n");
492 printf(" -u uninstall service\n");
493 printf(" -o remove the old .NET service\n");
494 }
496 int __cdecl
497 main(
498 __in ULONG argc,
499 __in_ecount(argc) PCHAR argv[]
500 )
501 {
502 SERVICE_TABLE_ENTRY service_table[2];
504 if (argc == 0)
505 {
506 print_usage("shutdownmon");
507 return 1;
508 }
509 if (argc != 2 || (argc == 2 && (strlen(argv[1]) != 2 || argv[1][0] != '-')))
510 {
511 print_usage(argv[0]);
512 return 1;
513 }
515 switch(argv[1][1])
516 {
517 case 'd':
518 service_status.dwCurrentState = SERVICE_RUNNING;
519 do_monitoring();
520 break;
521 case 's':
522 service_table[0].lpServiceName = SERVICE_ID;
523 service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
525 service_table[1].lpServiceName = NULL;
526 service_table[1].lpServiceProc = NULL;
528 StartServiceCtrlDispatcher(service_table);
529 break;
530 case 'i':
531 install_service();
532 break;
533 case 'u':
534 remove_service();
535 break;
536 case 'o':
537 remove_old_service();
538 break;
539 default:
540 print_usage(argv[0]);
541 return 1;
542 }
543 return 0;
544 }