win-pvdrivers

view shutdownmon/shutdownmon.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children 47fae39bc373
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 #define LOGFILE "C:\\xsm.log"
58 int write_log(char* str)
59 {
60 FILE* log;
61 log = fopen(LOGFILE, "a+");
62 if (log == NULL)
63 return -1;
64 fprintf(log, "%s\n", str);
65 fclose(log);
66 return 0;
67 }
69 static void
70 install_service()
71 {
72 SC_HANDLE manager_handle;
73 SC_HANDLE service_handle;
74 TCHAR path[MAX_PATH];
75 TCHAR command_line[MAX_PATH + 10];
77 if(!GetModuleFileName(NULL, path, MAX_PATH))
78 {
79 printf("Cannot install service (%d)\n", GetLastError());
80 return;
81 }
83 sprintf(command_line, "\"%s\" -s", path);
84 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
86 if (!manager_handle)
87 {
88 printf("OpenSCManager failed (%d)\n", GetLastError());
89 return;
90 }
92 service_handle = CreateService(
93 manager_handle, SERVICE_ID, SERVICE_NAME, SERVICE_ALL_ACCESS,
94 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
95 SERVICE_ERROR_NORMAL, command_line, NULL, NULL, NULL, NULL, NULL);
97 if (!service_handle)
98 {
99 printf("CreateService failed (%d)\n", GetLastError());
100 CloseServiceHandle(manager_handle);
101 return;
102 }
104 printf("Service installed\n");
106 CloseServiceHandle(service_handle);
107 CloseServiceHandle(manager_handle);
108 }
110 static void
111 remove_old_service()
112 {
113 SC_HANDLE manager_handle;
114 SC_HANDLE service_handle;
116 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
118 if (!manager_handle)
119 {
120 printf("OpenSCManager failed (%d)\n", GetLastError());
121 return;
122 }
124 service_handle = OpenService(manager_handle, OLD_SERVICE_ID, DELETE);
126 if (!service_handle)
127 {
128 printf("OpenService failed (%d)\n", GetLastError());
129 CloseServiceHandle(manager_handle);
130 return;
131 }
133 if (!DeleteService(service_handle))
134 {
135 printf("DeleteService failed (%d)\n", GetLastError());
136 CloseServiceHandle(service_handle);
137 CloseServiceHandle(manager_handle);
138 return;
139 }
141 printf("Old Service removed\n");
143 CloseServiceHandle(service_handle);
144 CloseServiceHandle(manager_handle);
145 }
147 static void
148 remove_service()
149 {
150 SC_HANDLE manager_handle;
151 SC_HANDLE service_handle;
153 manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
155 if (!manager_handle)
156 {
157 printf("OpenSCManager failed (%d)\n", GetLastError());
158 return;
159 }
161 service_handle = OpenService(manager_handle, SERVICE_ID, DELETE);
163 if (!service_handle)
164 {
165 printf("OpenService failed (%d)\n", GetLastError());
166 CloseServiceHandle(manager_handle);
167 return;
168 }
170 if (!DeleteService(service_handle))
171 {
172 printf("DeleteService failed (%d)\n", GetLastError());
173 CloseServiceHandle(service_handle);
174 CloseServiceHandle(manager_handle);
175 return;
176 }
178 printf("Service removed\n");
180 CloseServiceHandle(service_handle);
181 CloseServiceHandle(manager_handle);
182 }
184 static void
185 do_shutdown(BOOL bRebootAfterShutdown)
186 {
187 HANDLE proc_handle = GetCurrentProcess();
188 TOKEN_PRIVILEGES *tp;
189 HANDLE token_handle;
191 if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
192 return;
193 tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
194 tp->PrivilegeCount = 1;
195 if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
196 {
197 CloseHandle(token_handle);
198 return;
199 }
200 tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
201 if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
202 {
203 CloseHandle(token_handle);
204 return;
205 }
207 if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, bRebootAfterShutdown, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
208 {
209 // Log a message to the system log here about a failed shutdown
210 }
212 CloseHandle(token_handle);
213 }
215 static char *
216 get_xen_interface_path()
217 {
218 HDEVINFO handle;
219 SP_DEVICE_INTERFACE_DATA sdid;
220 SP_DEVICE_INTERFACE_DETAIL_DATA *sdidd;
221 DWORD buf_len;
222 char *path;
224 handle = SetupDiGetClassDevs(&GUID_XENBUS_IFACE, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
225 if (handle == INVALID_HANDLE_VALUE)
226 {
227 write_log("SetupDiGetClassDevs failed\n");
228 return NULL;
229 }
230 sdid.cbSize = sizeof(sdid);
231 if (!SetupDiEnumDeviceInterfaces(handle, NULL, &GUID_XENBUS_IFACE, 0, &sdid))
232 {
233 write_log("SetupDiEnumDeviceInterfaces failed\n");
234 return NULL;
235 }
236 SetupDiGetDeviceInterfaceDetail(handle, &sdid, NULL, 0, &buf_len, NULL);
237 sdidd = malloc(buf_len);
238 sdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
239 if (!SetupDiGetDeviceInterfaceDetail(handle, &sdid, sdidd, buf_len, NULL, NULL))
240 {
241 write_log("SetupDiGetDeviceInterfaceDetail failed\n");
242 return NULL;
243 }
245 path = malloc(strlen(sdidd->DevicePath) + 1);
246 strcpy(path, sdidd->DevicePath);
247 free(sdidd);
249 return path;
250 }
252 static int
253 xb_add_watch(HANDLE handle, char *path)
254 {
255 char buf[1024];
256 struct xsd_sockmsg *msg;
257 DWORD bytes_written;
258 DWORD bytes_read;
259 char *token = "0";
261 msg = (struct xsd_sockmsg *)buf;
262 msg->type = XS_WATCH;
263 msg->req_id = 0;
264 msg->tx_id = 0;
265 msg->len = (ULONG)(strlen(path) + 1 + strlen(token) + 1);
266 strcpy(buf + sizeof(*msg), path);
267 strcpy(buf + sizeof(*msg) + strlen(path) + 1, token);
269 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
270 {
271 printf("write failed\n");
272 return 0;
273 }
274 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
275 {
276 printf("read failed\n");
277 return 0;
278 }
279 printf("bytes_read = %d\n", bytes_read);
280 printf("msg->len = %d\n", msg->len);
281 buf[sizeof(*msg) + msg->len] = 0;
282 printf("msg text = %s\n", buf + sizeof(*msg));
284 return 1;
285 }
287 static int
288 xb_wait_event(HANDLE handle)
289 {
290 char buf[1024];
291 struct xsd_sockmsg *msg;
292 DWORD bytes_read;
294 printf("wait_event start\n");
295 msg = (struct xsd_sockmsg *)buf;
296 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
297 {
298 printf("read failed\n");
299 return 0;
300 }
301 printf("bytes_read = %d\n", bytes_read);
302 printf("msg->len = %d\n", msg->len);
303 buf[sizeof(*msg) + msg->len] = 0;
304 printf("msg text = %s\n", buf + sizeof(*msg));
305 return 1;
306 }
308 static char *
309 xb_read(HANDLE handle, char *path)
310 {
311 char buf[1024];
312 struct xsd_sockmsg *msg;
313 char *ret;
314 DWORD bytes_written;
315 DWORD bytes_read;
317 printf("read start\n");
318 msg = (struct xsd_sockmsg *)buf;
319 msg->type = XS_READ;
320 msg->req_id = 0;
321 msg->tx_id = 0;
322 msg->len = (ULONG)(strlen(path) + 1);
323 strcpy(buf + sizeof(*msg), path);
324 if (!WriteFile(handle, buf, sizeof(*msg) + msg->len, &bytes_written, NULL))
325 {
326 printf("write failed\n");
327 return NULL;
328 }
330 if (!ReadFile(handle, buf, 1024, &bytes_read, NULL))
331 {
332 printf("read failed\n");
333 return NULL;
334 }
335 printf("bytes_read = %d\n", bytes_read);
336 printf("msg->len = %d\n", msg->len);
337 buf[sizeof(*msg) + msg->len] = 0;
338 printf("msg text = %s\n", buf + sizeof(*msg));
339 ret = malloc(strlen(buf + sizeof(*msg)));
340 strcpy(ret, buf + sizeof(*msg));
341 return ret;
342 }
344 static void
345 do_monitoring()
346 {
347 HANDLE handle;
348 int state;
349 char *path;
350 char *buf;
352 path = get_xen_interface_path();
353 if (path == NULL)
354 return;
356 handle = CreateFile(path, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
358 xb_add_watch(handle, "control/shutdown");
360 state = 0;
361 while(xb_wait_event(handle))
362 {
363 if (service_status.dwCurrentState != SERVICE_RUNNING)
364 return;
365 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 write_log("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 write_log("RegisterServiceCtrlHandler failed\n");
422 return;
423 }
425 service_status.dwCurrentState = SERVICE_RUNNING;
426 SetServiceStatus(hStatus, &service_status);
428 do_monitoring();
430 write_log("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 }