win-pvdrivers

changeset 426:9b712742b8e8

Added C version of shutdownmon - no .NET required
author James Harper <james.harper@bendigoit.com.au>
date Mon Sep 08 22:10:14 2008 +1000 (2008-09-08)
parents ea14db3ca6f2
children 599061042271
files shutdownmon/makefile shutdownmon/shutdownmon.c shutdownmon/sources
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/shutdownmon/makefile	Mon Sep 08 22:10:14 2008 +1000
     1.3 @@ -0,0 +1,9 @@
     1.4 +#
     1.5 +# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
     1.6 +# file to this component.  This file merely indirects to the real make file
     1.7 +# that is shared by all the driver components of the Windows NT DDK
     1.8 +#
     1.9 +
    1.10 +!INCLUDE $(NTMAKEENV)\makefile.def
    1.11 +
    1.12 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/shutdownmon/shutdownmon.c	Mon Sep 08 22:10:14 2008 +1000
     2.3 @@ -0,0 +1,352 @@
     2.4 +#include <windows.h>
     2.5 +#include <basetyps.h>
     2.6 +#include <stdlib.h>
     2.7 +#include <wtypes.h>
     2.8 +#include <initguid.h>
     2.9 +#include <stdio.h>
    2.10 +#include <string.h>
    2.11 +#include <winioctl.h>
    2.12 +#include <setupapi.h>
    2.13 +#include <ctype.h>
    2.14 +
    2.15 +#define SERVICE_ID "ShutdownMon"
    2.16 +#define SERVICE_NAME "Xen Shutdown Monitor"
    2.17 +
    2.18 +SERVICE_STATUS service_status; 
    2.19 +SERVICE_STATUS_HANDLE hStatus; 
    2.20 +
    2.21 +#define LOGFILE "C:\\xsm.log"
    2.22 +
    2.23 +int write_log(char* str)
    2.24 +{
    2.25 +   FILE* log;
    2.26 +   log = fopen(LOGFILE, "a+");
    2.27 +   if (log == NULL)
    2.28 +      return -1;
    2.29 +   fprintf(log, "%s\n", str);
    2.30 +   fclose(log);
    2.31 +   return 0;
    2.32 +}
    2.33 +
    2.34 +static void
    2.35 +install_service()
    2.36 +{
    2.37 +  SC_HANDLE manager_handle;
    2.38 +  SC_HANDLE service_handle;
    2.39 +  TCHAR path[MAX_PATH];
    2.40 +  TCHAR command_line[MAX_PATH + 10];
    2.41 +
    2.42 +  if( !GetModuleFileName( NULL, path, MAX_PATH ) )
    2.43 +  {
    2.44 +    printf("Cannot install service (%d)\n", GetLastError());
    2.45 +    return;
    2.46 +  }
    2.47 +
    2.48 +  sprintf(command_line, "\"%s\" -s", path);
    2.49 +  manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    2.50 + 
    2.51 +  if (!manager_handle)
    2.52 +  {
    2.53 +    printf("OpenSCManager failed (%d)\n", GetLastError());
    2.54 +    return;
    2.55 +  }
    2.56 +
    2.57 +  service_handle = CreateService( 
    2.58 +    manager_handle, SERVICE_ID, SERVICE_NAME, SERVICE_ALL_ACCESS,
    2.59 +    SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
    2.60 +    SERVICE_ERROR_NORMAL, command_line, NULL, NULL, NULL, NULL, NULL);
    2.61 + 
    2.62 +  if (!service_handle) 
    2.63 +  {
    2.64 +    printf("CreateService failed (%d)\n", GetLastError()); 
    2.65 +    CloseServiceHandle(manager_handle);
    2.66 +    return;
    2.67 +  }
    2.68 +
    2.69 +  printf("Service installed\n"); 
    2.70 +
    2.71 +  CloseServiceHandle(service_handle); 
    2.72 +  CloseServiceHandle(manager_handle);
    2.73 +}
    2.74 +
    2.75 +static void
    2.76 +remove_service()
    2.77 +{
    2.78 +  SC_HANDLE manager_handle;
    2.79 +  SC_HANDLE service_handle;
    2.80 +
    2.81 +  manager_handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    2.82 + 
    2.83 +  if (!manager_handle)
    2.84 +  {
    2.85 +    printf("OpenSCManager failed (%d)\n", GetLastError());
    2.86 +    return;
    2.87 +  }
    2.88 +
    2.89 +  service_handle = OpenService(manager_handle, SERVICE_ID, DELETE);
    2.90 + 
    2.91 +  if (!service_handle) 
    2.92 +  {
    2.93 +    printf("OpenService failed (%d)\n", GetLastError()); 
    2.94 +    CloseServiceHandle(manager_handle);
    2.95 +    return;
    2.96 +  }
    2.97 +
    2.98 +  if (!DeleteService(service_handle))
    2.99 +  {
   2.100 +    printf("DeleteService failed (%d)\n", GetLastError()); 
   2.101 +    CloseServiceHandle(service_handle); 
   2.102 +    CloseServiceHandle(manager_handle);
   2.103 +    return;
   2.104 +  }
   2.105 +
   2.106 +  printf("Service removed\n"); 
   2.107 +
   2.108 +  CloseServiceHandle(service_handle); 
   2.109 +  CloseServiceHandle(manager_handle);
   2.110 +}
   2.111 +
   2.112 +static void
   2.113 +do_shutdown(BOOL bRebootAfterShutdown)
   2.114 +{
   2.115 +  HANDLE proc_handle = GetCurrentProcess();
   2.116 +  TOKEN_PRIVILEGES *tp;
   2.117 +  HANDLE token_handle;
   2.118 +
   2.119 +  if (!OpenProcessToken(proc_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
   2.120 +    return;
   2.121 +  tp = malloc(sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES));
   2.122 +  tp->PrivilegeCount = 1;
   2.123 +  if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid))
   2.124 +  {
   2.125 +    CloseHandle(token_handle);
   2.126 +    return;
   2.127 +  }
   2.128 +  tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   2.129 +  if (!AdjustTokenPrivileges(token_handle, FALSE, tp, 0, NULL, NULL))
   2.130 +  {
   2.131 +    CloseHandle(token_handle);
   2.132 +    return;
   2.133 +  }
   2.134 +
   2.135 +  if (!InitiateSystemShutdownEx(NULL, NULL, 0, TRUE, bRebootAfterShutdown, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
   2.136 +  {
   2.137 +    // Log a message to the system log here about a failed shutdown
   2.138 +  }
   2.139 +
   2.140 +  CloseHandle(token_handle);
   2.141 +}
   2.142 +
   2.143 +DEFINE_GUID(GUID_XEN_IFACE, 0x5C568AC5, 0x9DDF, 0x4FA5, 0xA9, 0x4A, 0x39, 0xD6, 0x70, 0x77, 0x81, 0x9C);
   2.144 +
   2.145 +static char *
   2.146 +get_xen_interface_path()
   2.147 +{
   2.148 +  HDEVINFO handle = SetupDiGetClassDevs(&GUID_XEN_IFACE, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
   2.149 +  SP_DEVICE_INTERFACE_DATA sdid;
   2.150 +  SP_DEVICE_INTERFACE_DETAIL_DATA *sdidd;
   2.151 +  DWORD buf_len;
   2.152 +  char *path;
   2.153 +
   2.154 +  sdid.cbSize = sizeof(sdid);
   2.155 +  if (!SetupDiEnumDeviceInterfaces(handle, NULL, &GUID_XEN_IFACE, 0, &sdid))
   2.156 +    return NULL;
   2.157 +  SetupDiGetDeviceInterfaceDetail(handle, &sdid, NULL, 0, &buf_len, NULL);
   2.158 +  printf("buf_len = %d\n", buf_len);
   2.159 +  sdidd = malloc(buf_len);
   2.160 +  sdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
   2.161 +  if (!SetupDiGetDeviceInterfaceDetail(handle, &sdid, sdidd, buf_len, NULL, NULL))
   2.162 +    return NULL;
   2.163 +  
   2.164 +  path = malloc(strlen(sdidd->DevicePath) + 1);
   2.165 +  strcpy(path, sdidd->DevicePath);
   2.166 +  free(sdidd);
   2.167 +  
   2.168 +  return path;
   2.169 +}
   2.170 +
   2.171 +static void
   2.172 +do_monitoring()
   2.173 +{
   2.174 +  char buf[1024];
   2.175 +  char *bufptr = buf;
   2.176 +  HANDLE handle;
   2.177 +  int state;
   2.178 +  char *path;
   2.179 +  DWORD bytes_read;
   2.180 +  char inchar;
   2.181 +
   2.182 +  path = get_xen_interface_path();
   2.183 +  if (path == NULL)
   2.184 +    return;
   2.185 +
   2.186 +  handle = CreateFile(path, FILE_GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   2.187 +
   2.188 +  state = 0;
   2.189 +  for (;;)
   2.190 +  {
   2.191 +    if (service_status.dwCurrentState != SERVICE_RUNNING)
   2.192 +      return;
   2.193 +    if (!ReadFile(handle, &inchar, 1, &bytes_read, NULL))
   2.194 +    {
   2.195 +      CloseHandle(handle);
   2.196 +      return;
   2.197 +    }
   2.198 +    switch (state)
   2.199 +    {
   2.200 +    case 0:
   2.201 +      if (isalnum(inchar))
   2.202 +      {
   2.203 +        *bufptr = inchar;
   2.204 +        bufptr++;
   2.205 +      }
   2.206 +      else if (inchar == '\r')
   2.207 +      {
   2.208 +        *bufptr = 0;
   2.209 +        state = 1;
   2.210 +      }
   2.211 +      else
   2.212 +      {
   2.213 +        bufptr = buf;
   2.214 +      }
   2.215 +      break;
   2.216 +    case 1:
   2.217 +      if (inchar == '\n')
   2.218 +      {
   2.219 +        printf("%s\n", buf);
   2.220 +        if (strcmp("poweroff", buf) == 0 || strcmp("halt", buf) == 0)
   2.221 +        {
   2.222 +          do_shutdown(FALSE);
   2.223 +        }
   2.224 +        else if (strcmp("reboot", buf) == 0)
   2.225 +        {
   2.226 +          do_shutdown(TRUE);
   2.227 +        } 
   2.228 +        else
   2.229 +        {
   2.230 +          // complain here
   2.231 +        }
   2.232 +      }
   2.233 +      state = 0;
   2.234 +      break;
   2.235 +    }
   2.236 +  }
   2.237 +}
   2.238 +
   2.239 +void control_handler(DWORD request) 
   2.240 +{ 
   2.241 +  switch(request) 
   2.242 +  { 
   2.243 +    case SERVICE_CONTROL_STOP: 
   2.244 +      service_status.dwWin32ExitCode = 0; 
   2.245 +      service_status.dwCurrentState = SERVICE_STOPPED; 
   2.246 +      SetServiceStatus (hStatus, &service_status);
   2.247 +      return; 
   2.248 + 
   2.249 +    case SERVICE_CONTROL_SHUTDOWN: 
   2.250 +      service_status.dwWin32ExitCode = 0; 
   2.251 +      service_status.dwCurrentState = SERVICE_STOPPED; 
   2.252 +      SetServiceStatus (hStatus, &service_status);
   2.253 +      return; 
   2.254 +
   2.255 +    default:
   2.256 +      break;
   2.257 +  } 
   2.258 + 
   2.259 +  SetServiceStatus (hStatus, &service_status);
   2.260 +
   2.261 +  return; 
   2.262 +}
   2.263 +
   2.264 +void service_main(int argc, char *argv[]) 
   2.265 +{ 
   2.266 +  int error; 
   2.267 +
   2.268 +write_log("Entering service_main\n"); 
   2.269 +
   2.270 +  service_status.dwServiceType = SERVICE_WIN32; 
   2.271 +  service_status.dwCurrentState =  SERVICE_START_PENDING; 
   2.272 +  service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
   2.273 +  service_status.dwWin32ExitCode = 0; 
   2.274 +  service_status.dwServiceSpecificExitCode = 0; 
   2.275 +  service_status.dwCheckPoint = 0; 
   2.276 +  service_status.dwWaitHint = 0; 
   2.277 + 
   2.278 +  hStatus = RegisterServiceCtrlHandler(SERVICE_ID, (LPHANDLER_FUNCTION)control_handler); 
   2.279 +  if (hStatus == (SERVICE_STATUS_HANDLE)0) 
   2.280 +  { 
   2.281 +    write_log("RegisterServiceCtrlHandler failed\n"); 
   2.282 +    return; 
   2.283 +  }  
   2.284 +
   2.285 +  service_status.dwCurrentState = SERVICE_RUNNING; 
   2.286 +  SetServiceStatus(hStatus, &service_status);
   2.287 +
   2.288 +  do_monitoring();
   2.289 +
   2.290 +write_log("All done\n"); 
   2.291 +
   2.292 +  return; 
   2.293 +}
   2.294 +
   2.295 +
   2.296 +static void
   2.297 +print_usage(char *name)
   2.298 +{
   2.299 +  printf("Usage:\n");
   2.300 +  printf("  %s <options>\n", name);
   2.301 +  printf("\n");
   2.302 +  printf("Options:\n");
   2.303 +  printf(" -d run in foreground\n");
   2.304 +  printf(" -s run as service\n");
   2.305 +  printf(" -i install service\n");
   2.306 +  printf(" -u uninstall service\n");
   2.307 +}
   2.308 +
   2.309 +int __cdecl
   2.310 +main(
   2.311 +    __in ULONG argc,
   2.312 +    __in_ecount(argc) PCHAR argv[]
   2.313 +)
   2.314 +{
   2.315 +  SERVICE_TABLE_ENTRY service_table[2];
   2.316 +
   2.317 +  if (argc == 0)
   2.318 +  {
   2.319 +    print_usage("shutdownmon");
   2.320 +    return 1;
   2.321 +  }
   2.322 +  if (argc != 2 || (argc == 2 && (strlen(argv[1]) != 2 || argv[1][0] != '-')))
   2.323 +  {
   2.324 +    print_usage(argv[0]);
   2.325 +    return 1;
   2.326 +  }
   2.327 +
   2.328 +  switch(argv[1][1])
   2.329 +  {
   2.330 +  case 'd':
   2.331 +    service_status.dwCurrentState = SERVICE_RUNNING;
   2.332 +    do_monitoring();
   2.333 +    break;
   2.334 +  case 's':
   2.335 +    service_table[0].lpServiceName = SERVICE_ID;
   2.336 +    service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
   2.337 +
   2.338 +    service_table[1].lpServiceName = NULL;
   2.339 +    service_table[1].lpServiceProc = NULL;
   2.340 +
   2.341 +    StartServiceCtrlDispatcher(service_table);
   2.342 +    break;
   2.343 +  case 'i':
   2.344 +    install_service();
   2.345 +    break;
   2.346 +  case 'u':
   2.347 +    remove_service();
   2.348 +    break;
   2.349 +  default:
   2.350 +    print_usage(argv[0]);
   2.351 +    return 1;
   2.352 +  }
   2.353 +  return 0;
   2.354 +}
   2.355 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/shutdownmon/sources	Mon Sep 08 22:10:14 2008 +1000
     3.3 @@ -0,0 +1,11 @@
     3.4 +TARGETNAME=shutdownmon
     3.5 +TARGETTYPE=PROGRAM
     3.6 +TARGETPATH=..\Target
     3.7 +TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\setupapi.lib
     3.8 +UMTYPE=console
     3.9 +#UMTYPE=windows
    3.10 +UMENTRY=main
    3.11 +UMBASE=0x400000
    3.12 +_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WIN2K)
    3.13 +SOURCES=shutdownmon.c
    3.14 +USE_MSVCRT=1