win-pvdrivers

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