Class: Puppet::Util::Windows::Daemon

Inherits:
Object
  • Object
show all
Extended by:
FFI::Windows::Constants, FFI::Windows::Functions, FFI::Windows::Structs
Includes:
FFI::Windows::Constants, FFI::Windows::Functions, FFI::Windows::Structs
Defined in:
lib/puppet/util/windows/daemon.rb

Overview

The Daemon class, based on the chef/win32-service implementation

Direct Known Subclasses

WindowsDaemon

Constant Summary collapse

STOPPED =

Service is not running

SERVICE_STOPPED
START_PENDING =

Service has received a start signal but is not yet running

SERVICE_START_PENDING
STOP_PENDING =

Service has received a stop signal but is not yet stopped

SERVICE_STOP_PENDING
RUNNING =

Service is running

SERVICE_RUNNING
CONTINUE_PENDING =

Service has received a signal to resume but is not yet running

SERVICE_CONTINUE_PENDING
PAUSE_PENDING =

Service has received a signal to pause but is not yet paused

SERVICE_PAUSE_PENDING
PAUSED =

Service is paused

SERVICE_PAUSED
CONTROL_STOP =

Notifies service that it should stop

SERVICE_CONTROL_STOP
CONTROL_PAUSE =

Notifies service that it should pause

SERVICE_CONTROL_PAUSE
CONTROL_CONTINUE =

Notifies service that it should resume

SERVICE_CONTROL_CONTINUE
CONTROL_INTERROGATE =

Notifies service that it should return its current status information

SERVICE_CONTROL_INTERROGATE
CONTROL_PARAMCHANGE =

Notifies a service that its parameters have changed

SERVICE_CONTROL_PARAMCHANGE
CONTROL_NETBINDADD =

Notifies a service that there is a new component for binding

SERVICE_CONTROL_NETBINDADD
CONTROL_NETBINDREMOVE =

Notifies a service that a component for binding has been removed

SERVICE_CONTROL_NETBINDREMOVE
CONTROL_NETBINDENABLE =

Notifies a service that a component for binding has been enabled

SERVICE_CONTROL_NETBINDENABLE
CONTROL_NETBINDDISABLE =

Notifies a service that a component for binding has been disabled

SERVICE_CONTROL_NETBINDDISABLE
IDLE =
0
IDLE_CONTROL_CODE =

Misc

0
WAIT_OBJECT_0 =
0
WAIT_TIMEOUT =
0x00000102
WAIT_FAILED =
0xFFFFFFFF
NO_ERROR =
0
SetTheServiceStatus =

Wraps SetServiceStatus.

proc do |dwCurrentState, dwWin32ExitCode, dwCheckPoint, dwWaitHint|
  ss = SERVICE_STATUS.new # Current status of the service.

  # Disable control requests until the service is started.
  if dwCurrentState == SERVICE_START_PENDING
    ss[:dwControlsAccepted] = 0
  else
    ss[:dwControlsAccepted] =
      SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
      SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE
  end

  # Initialize ss structure.
  ss[:dwServiceType]             = SERVICE_WIN32_OWN_PROCESS
  ss[:dwServiceSpecificExitCode] = 0
  ss[:dwCurrentState]            = dwCurrentState
  ss[:dwWin32ExitCode]           = dwWin32ExitCode
  ss[:dwCheckPoint]              = dwCheckPoint
  ss[:dwWaitHint]                = dwWaitHint

  @@dwServiceState = dwCurrentState

  # Send status of the service to the Service Controller.
  unless SetServiceStatus(@@ssh, ss)
    SetEvent(@@hStopEvent)
  end
end
ERROR_CALL_NOT_IMPLEMENTED =
0x78
Service_Ctrl_ex =

Handles control signals from the service control manager.

proc do |dwCtrlCode, _dwEventType, _lpEventData, _lpContext|
  @@waiting_control_code = dwCtrlCode;
  return_value = NO_ERROR

  begin
    dwState = SERVICE_RUNNING

    case dwCtrlCode
    when SERVICE_CONTROL_STOP
      dwState = SERVICE_STOP_PENDING
    when SERVICE_CONTROL_SHUTDOWN
      dwState = SERVICE_STOP_PENDING
    when SERVICE_CONTROL_PAUSE
      dwState = SERVICE_PAUSED
    when SERVICE_CONTROL_CONTINUE
      dwState = SERVICE_RUNNING
      # else
      # TODO: Handle other control codes? Retain the current state?
    end

    # Set the status of the service except on interrogation.
    unless dwCtrlCode == SERVICE_CONTROL_INTERROGATE
      SetTheServiceStatus.call(dwState, NO_ERROR, 0, 0)
    end

    # Tell service_main thread to stop.
    if dwCtrlCode == SERVICE_CONTROL_STOP || dwCtrlCode == SERVICE_CONTROL_SHUTDOWN
      if SetEvent(@@hStopEvent) == 0
        SetTheServiceStatus.call(SERVICE_STOPPED, FFI.errno, 0, 0)
      end
    end
  rescue
    return_value = ERROR_CALL_NOT_IMPLEMENTED
  end

  return_value
end
Service_Main =

Called by the service control manager after the call to StartServiceCtrlDispatcher.

FFI::Function.new(:void, [:ulong, :pointer], :blocking => false) do |dwArgc, lpszArgv|
  # Obtain the name of the service.
  if lpszArgv.address != 0
    argv = lpszArgv.get_array_of_string(0, dwArgc)
    lpszServiceName = argv[0]
  else
    lpszServiceName = ''
  end

  # Args passed to Service.start
  if dwArgc > 1
    @@Argv = argv[1..]
  else
    @@Argv = nil
  end

  # Register the service ctrl handler.
  @@ssh = RegisterServiceCtrlHandlerExW(
    lpszServiceName,
    Service_Ctrl_ex,
    nil
  )

  # No service to stop, no service handle to notify, nothing to do but exit.
  break if @@ssh == 0

  # The service has started.
  SetTheServiceStatus.call(SERVICE_RUNNING, NO_ERROR, 0, 0)

  SetEvent(@@hStartEvent)

  # Main loop for the service.
  while WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0
  end

  # Main loop for the service.
  while WaitForSingleObject(@@hStopCompletedEvent, 1000) != WAIT_OBJECT_0
  end
ensure
  # Stop the service.
  SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
end
ThreadProc =
FFI::Function.new(:ulong, [:pointer]) do |lpParameter|
  ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRYW, 2)

  s = SERVICE_TABLE_ENTRYW.new(ste[0])
  s[:lpServiceName] = FFI::MemoryPointer.from_string('')
  s[:lpServiceProc] = lpParameter

  s = SERVICE_TABLE_ENTRYW.new(ste[1])
  s[:lpServiceName] = nil
  s[:lpServiceProc] = nil

  # No service to step, no service handle, no ruby exceptions, just terminate the thread..
  unless StartServiceCtrlDispatcherW(ste)
    return 1
  end

  return 0
end

Constants included from FFI::Windows::Constants

FFI::Windows::Constants::ABOVE_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::ALL_SERVICE_TYPES, FFI::Windows::Constants::BELOW_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::CREATE_BREAKAWAY_FROM_JOB, FFI::Windows::Constants::CREATE_DEFAULT_ERROR_MODE, FFI::Windows::Constants::CREATE_NEW_CONSOLE, FFI::Windows::Constants::CREATE_NEW_PROCESS_GROUP, FFI::Windows::Constants::CREATE_NO_WINDOW, FFI::Windows::Constants::CREATE_PRESERVE_CODE_AUTHZ_LEVEL, FFI::Windows::Constants::CREATE_PROTECTED_PROCESS, FFI::Windows::Constants::CREATE_SEPARATE_WOW_VDM, FFI::Windows::Constants::CREATE_SHARED_WOW_VDM, FFI::Windows::Constants::CREATE_SUSPENDED, FFI::Windows::Constants::CREATE_UNICODE_ENVIRONMENT, FFI::Windows::Constants::DEBUG_ONLY_THIS_PROCESS, FFI::Windows::Constants::DEBUG_PROCESS, FFI::Windows::Constants::DELETE, FFI::Windows::Constants::DETACHED_PROCESS, FFI::Windows::Constants::ERROR_ALREADY_EXISTS, FFI::Windows::Constants::ERROR_FILE_NOT_FOUND, FFI::Windows::Constants::ERROR_PATH_NOT_FOUND, FFI::Windows::Constants::ERROR_SERVICE_DOES_NOT_EXIST, FFI::Windows::Constants::FILE_ALL_ACCESS, FFI::Windows::Constants::FILE_APPEND_DATA, FFI::Windows::Constants::FILE_ATTRIBUTE_DIRECTORY, FFI::Windows::Constants::FILE_ATTRIBUTE_READONLY, FFI::Windows::Constants::FILE_ATTRIBUTE_REPARSE_POINT, FFI::Windows::Constants::FILE_DELETE_CHILD, FFI::Windows::Constants::FILE_DEVICE_FILE_SYSTEM, FFI::Windows::Constants::FILE_EXECUTE, FFI::Windows::Constants::FILE_FLAG_BACKUP_SEMANTICS, FFI::Windows::Constants::FILE_FLAG_OPEN_REPARSE_POINT, FFI::Windows::Constants::FILE_GENERIC_EXECUTE, FFI::Windows::Constants::FILE_GENERIC_READ, FFI::Windows::Constants::FILE_GENERIC_WRITE, FFI::Windows::Constants::FILE_READ_ATTRIBUTES, FFI::Windows::Constants::FILE_READ_DATA, FFI::Windows::Constants::FILE_READ_EA, FFI::Windows::Constants::FILE_SHARE_READ, FFI::Windows::Constants::FILE_SHARE_WRITE, FFI::Windows::Constants::FILE_WRITE_ATTRIBUTES, FFI::Windows::Constants::FILE_WRITE_DATA, FFI::Windows::Constants::FILE_WRITE_EA, FFI::Windows::Constants::FINAL_STATES, FFI::Windows::Constants::FSCTL_GET_REPARSE_POINT, FFI::Windows::Constants::GENERIC_ALL, FFI::Windows::Constants::GENERIC_EXECUTE, FFI::Windows::Constants::GENERIC_READ, FFI::Windows::Constants::GENERIC_WRITE, FFI::Windows::Constants::HANDLE_FLAG_INHERIT, FFI::Windows::Constants::HIGH_PRIORITY_CLASS, FFI::Windows::Constants::IDLE_PRIORITY_CLASS, FFI::Windows::Constants::INHERIT_PARENT_AFFINITY, FFI::Windows::Constants::INVALID_FILE_ATTRIBUTES, FFI::Windows::Constants::INVALID_HANDLE_VALUE, FFI::Windows::Constants::IO_REPARSE_TAG_CSV, FFI::Windows::Constants::IO_REPARSE_TAG_DEDUP, FFI::Windows::Constants::IO_REPARSE_TAG_DFS, FFI::Windows::Constants::IO_REPARSE_TAG_DFSR, FFI::Windows::Constants::IO_REPARSE_TAG_HSM, FFI::Windows::Constants::IO_REPARSE_TAG_HSM2, FFI::Windows::Constants::IO_REPARSE_TAG_MOUNT_POINT, FFI::Windows::Constants::IO_REPARSE_TAG_NFS, FFI::Windows::Constants::IO_REPARSE_TAG_SIS, FFI::Windows::Constants::IO_REPARSE_TAG_SYMLINK, FFI::Windows::Constants::IO_REPARSE_TAG_WIM, FFI::Windows::Constants::LOGON_WITH_PROFILE, FFI::Windows::Constants::MAXIMUM_REPARSE_DATA_BUFFER_SIZE, FFI::Windows::Constants::METHOD_BUFFERED, FFI::Windows::Constants::NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::OPEN_EXISTING, FFI::Windows::Constants::PROCESS_ALL_ACCESS, FFI::Windows::Constants::PROCESS_QUERY_INFORMATION, FFI::Windows::Constants::PROCESS_SET_INFORMATION, FFI::Windows::Constants::PROCESS_TERMINATE, FFI::Windows::Constants::PROCESS_VM_READ, FFI::Windows::Constants::REALTIME_PRIORITY_CLASS, FFI::Windows::Constants::REPLACEFILE_IGNORE_ACL_ERRORS, FFI::Windows::Constants::REPLACEFILE_IGNORE_MERGE_ERRORS, FFI::Windows::Constants::REPLACEFILE_WRITE_THROUGH, FFI::Windows::Constants::SC_MANAGER_ALL_ACCESS, FFI::Windows::Constants::SC_MANAGER_CONNECT, FFI::Windows::Constants::SC_MANAGER_CREATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_ENUMERATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_LOCK, FFI::Windows::Constants::SC_MANAGER_MODIFY_BOOT_CONFIG, FFI::Windows::Constants::SC_MANAGER_QUERY_LOCK_STATUS, FFI::Windows::Constants::SEM_FAILCRITICALERRORS, FFI::Windows::Constants::SEM_NOGPFAULTERRORBOX, FFI::Windows::Constants::SERVICENAME_MAX, FFI::Windows::Constants::SERVICE_ACCEPT_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_NETBINDCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PARAMCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_ACCEPT_POWEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_SHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_STOP, FFI::Windows::Constants::SERVICE_ACCEPT_TIMECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_USER_LOGOFF, FFI::Windows::Constants::SERVICE_ACTIVE, FFI::Windows::Constants::SERVICE_ALL_ACCESS, FFI::Windows::Constants::SERVICE_AUTO_START, FFI::Windows::Constants::SERVICE_BOOT_START, FFI::Windows::Constants::SERVICE_CHANGE_CONFIG, FFI::Windows::Constants::SERVICE_CONFIG_DELAYED_AUTO_START_INFO, FFI::Windows::Constants::SERVICE_CONFIG_DESCRIPTION, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, FFI::Windows::Constants::SERVICE_CONFIG_LAUNCH_PROTECTED, FFI::Windows::Constants::SERVICE_CONFIG_PREFERRED_NODE, FFI::Windows::Constants::SERVICE_CONFIG_PRESHUTDOWN_INFO, FFI::Windows::Constants::SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, FFI::Windows::Constants::SERVICE_CONFIG_SERVICE_SID_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TRIGGER_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TYPES, FFI::Windows::Constants::SERVICE_CONTINUE_PENDING, FFI::Windows::Constants::SERVICE_CONTROL_CONTINUE, FFI::Windows::Constants::SERVICE_CONTROL_DEVICEEVENT, FFI::Windows::Constants::SERVICE_CONTROL_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_INTERROGATE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDADD, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDDISABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDENABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDREMOVE, FFI::Windows::Constants::SERVICE_CONTROL_PARAMCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_PAUSE, FFI::Windows::Constants::SERVICE_CONTROL_POWEREVENT, FFI::Windows::Constants::SERVICE_CONTROL_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_SHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SIGNALS, FFI::Windows::Constants::SERVICE_CONTROL_STOP, FFI::Windows::Constants::SERVICE_CONTROL_TIMECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_DEMAND_START, FFI::Windows::Constants::SERVICE_DISABLED, FFI::Windows::Constants::SERVICE_ENUMERATE_DEPENDENTS, FFI::Windows::Constants::SERVICE_FILE_SYSTEM_DRIVER, FFI::Windows::Constants::SERVICE_INACTIVE, FFI::Windows::Constants::SERVICE_INTERACTIVE_PROCESS, FFI::Windows::Constants::SERVICE_INTERROGATE, FFI::Windows::Constants::SERVICE_KERNEL_DRIVER, FFI::Windows::Constants::SERVICE_NO_CHANGE, FFI::Windows::Constants::SERVICE_PAUSED, FFI::Windows::Constants::SERVICE_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_PAUSE_PENDING, FFI::Windows::Constants::SERVICE_QUERY_CONFIG, FFI::Windows::Constants::SERVICE_QUERY_STATUS, FFI::Windows::Constants::SERVICE_RUNNING, FFI::Windows::Constants::SERVICE_START, FFI::Windows::Constants::SERVICE_START_PENDING, FFI::Windows::Constants::SERVICE_START_TYPES, FFI::Windows::Constants::SERVICE_STATES, FFI::Windows::Constants::SERVICE_STATE_ALL, FFI::Windows::Constants::SERVICE_STOP, FFI::Windows::Constants::SERVICE_STOPPED, FFI::Windows::Constants::SERVICE_STOP_PENDING, FFI::Windows::Constants::SERVICE_SYSTEM_START, FFI::Windows::Constants::SERVICE_USER_DEFINED_CONTROL, FFI::Windows::Constants::SERVICE_USER_OWN_PROCESS, FFI::Windows::Constants::SERVICE_USER_SHARE_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_OWN_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_SHARE_PROCESS, FFI::Windows::Constants::SHGFI_DISPLAYNAME, FFI::Windows::Constants::SHGFI_PIDL, FFI::Windows::Constants::SPECIFIC_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_EXECUTE, FFI::Windows::Constants::STANDARD_RIGHTS_READ, FFI::Windows::Constants::STANDARD_RIGHTS_REQUIRED, FFI::Windows::Constants::STANDARD_RIGHTS_WRITE, FFI::Windows::Constants::STARTF_USESTDHANDLES, FFI::Windows::Constants::SYNCHRONIZE, FFI::Windows::Constants::TOKEN_INFORMATION_CLASS, FFI::Windows::Constants::UNSAFE_PENDING_STATES, FFI::Windows::Constants::WRITE_DAC, FFI::Windows::Constants::WRITE_OWNER

Constants included from FFI::Windows::Structs

FFI::Windows::Structs::MAXIMUM_REPARSE_DATA_BUFFER_SIZE

Constants included from FFI::Windows::Functions

FFI::Windows::Functions::SC_ENUM_TYPE, FFI::Windows::Functions::SC_STATUS_TYPE

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.mainloopObject

This is a shortcut for Daemon.new + Daemon#mainloop.



211
212
213
# File 'lib/puppet/util/windows/daemon.rb', line 211

def self.mainloop
  new.mainloop
end

Instance Method Details

#mainloopObject

This is the method that actually puts your code into a loop and allows it to run as a service. The code that is actually run while in the mainloop is what you defined in your own Daemon#service_main method.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/puppet/util/windows/daemon.rb', line 219

def mainloop
  @@waiting_control_code = IDLE_CONTROL_CODE
  @@dwServiceState = 0

  # Redirect STDIN, STDOUT and STDERR to the NUL device if they're still
  # associated with a tty. This helps newbs avoid Errno::EBADF errors.
  STDIN.reopen('NUL') if STDIN.isatty
  STDOUT.reopen('NUL') if STDOUT.isatty
  STDERR.reopen('NUL') if STDERR.isatty

  # Calling init here so that init failures never even tries to start the
  # service. Of course that means that init methods must be very quick
  # because the SCM will be receiving no START_PENDING messages while
  # init's running.
  #
  # TODO: Fix?
  service_init() if respond_to?('service_init')

  # Create the event to signal the service to start.
  @@hStartEvent = CreateEventW(nil, 1, 0, nil)

  if @@hStartEvent == 0
    raise SystemCallError.new('CreateEvent', FFI.errno)
  end

  # Create the event to signal the service to stop.
  @@hStopEvent = CreateEventW(nil, 1, 0, nil)

  if @@hStopEvent == 0
    raise SystemCallError.new('CreateEvent', FFI.errno)
  end

  # Create the event to signal the service that stop has completed
  @@hStopCompletedEvent = CreateEventW(nil, 1, 0, nil)

  if @@hStopCompletedEvent == 0
    raise SystemCallError.new('CreateEvent', FFI.errno)
  end

  hThread = CreateThread(nil, 0, ThreadProc, Service_Main, 0, nil)

  if hThread == 0
    raise SystemCallError.new('CreateThread', FFI.errno)
  end

  events = FFI::MemoryPointer.new(:pointer, 2)
  events.put_pointer(0, FFI::Pointer.new(hThread))
  events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent))

  while (index = WaitForMultipleObjects(2, events, 0, 1000)) == WAIT_TIMEOUT
  end

  if index == WAIT_FAILED
    raise SystemCallError.new('WaitForMultipleObjects', FFI.errno)
  end

  # The thread exited, so the show is off.
  if index == WAIT_OBJECT_0
    raise "Service_Main thread exited abnormally"
  end

  thr = Thread.new do
    while WaitForSingleObject(@@hStopEvent, 1000) == WAIT_TIMEOUT
      # Check to see if anything interesting has been signaled
      case @@waiting_control_code
      when SERVICE_CONTROL_PAUSE
        service_pause() if respond_to?('service_pause')
      when SERVICE_CONTROL_CONTINUE
        service_resume() if respond_to?('service_resume')
      when SERVICE_CONTROL_INTERROGATE
        service_interrogate() if respond_to?('service_interrogate')
      when SERVICE_CONTROL_SHUTDOWN
        service_shutdown() if respond_to?('service_shutdown')
      when SERVICE_CONTROL_PARAMCHANGE
        service_paramchange() if respond_to?('service_paramchange')
      when SERVICE_CONTROL_NETBINDADD
        service_netbindadd() if respond_to?('service_netbindadd')
      when SERVICE_CONTROL_NETBINDREMOVE
        service_netbindremove() if respond_to?('service_netbindremove')
      when SERVICE_CONTROL_NETBINDENABLE
        service_netbindenable() if respond_to?('service_netbindenable')
      when SERVICE_CONTROL_NETBINDDISABLE
        service_netbinddisable() if respond_to?('service_netbinddisable')
      end
      @@waiting_control_code = IDLE_CONTROL_CODE
    end

    service_stop() if respond_to?('service_stop')
  ensure
    SetEvent(@@hStopCompletedEvent)
  end

  if respond_to?('service_main')
    service_main(*@@Argv)
  end

  thr.join
end

#running?Boolean

Returns whether or not the service is in a running state, i.e. the service status is either RUNNING, PAUSED or IDLE.

This is typically used within your service_main method to setup the main loop. For example:

class MyDaemon < Daemon
   def service_main
      while running?
         # Your main loop here
      end
   end
end

Returns:

  • (Boolean)


353
354
355
# File 'lib/puppet/util/windows/daemon.rb', line 353

def running?
  [SERVICE_RUNNING, SERVICE_PAUSED, 0].include?(@@dwServiceState)
end

#stateObject

Returns the state of the service (as an constant integer) which can be any of the service status constants, e.g. RUNNING, PAUSED, etc.

This method is typically used within your service_main method to setup the loop. For example:

class MyDaemon < Daemon
  def service_main
    while state == RUNNING || state == PAUSED || state == IDLE
      # Your main loop here
    end
  end
end

See the Daemon#running? method for an abstraction of the above code.



334
335
336
# File 'lib/puppet/util/windows/daemon.rb', line 334

def state
  @@dwServiceState
end