win-pvdrivers

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