win32-svc.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright (c) 2002 - 2003
  3. * NetGroup, Politecnico di Torino (Italy)
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the Politecnico di Torino nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. */
  32. #include "rpcapd.h"
  33. #include <pcap.h> // for PCAP_ERRBUF_SIZE
  34. #include "sockutils.h" // for SOCK_DEBUG_MESSAGE
  35. #include "portability.h"
  36. #include "fileconf.h"
  37. static SERVICE_STATUS_HANDLE service_status_handle;
  38. static SERVICE_STATUS service_status;
  39. void svc_geterr(char *str);
  40. static void WINAPI svc_main(DWORD argc, char **argv);
  41. static void update_svc_status(DWORD state, DWORD progress_indicator);
  42. int svc_start(void)
  43. {
  44. int rc;
  45. SERVICE_TABLE_ENTRY ste[] =
  46. {
  47. { PROGRAM_NAME, svc_main },
  48. { NULL, NULL }
  49. };
  50. // This call is blocking. A new thread is created which will launch
  51. // the svc_main() function
  52. if ( (rc = StartServiceCtrlDispatcher(ste)) == 0)
  53. svc_geterr("StartServiceCtrlDispatcher()");
  54. return rc; // FALSE if this is not started as a service
  55. }
  56. void svc_geterr(char *str)
  57. {
  58. char message[PCAP_ERRBUF_SIZE];
  59. char string[PCAP_ERRBUF_SIZE];
  60. int val;
  61. val = GetLastError();
  62. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
  63. FORMAT_MESSAGE_MAX_WIDTH_MASK,
  64. NULL, val, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  65. (LPSTR) string, PCAP_ERRBUF_SIZE, NULL);
  66. pcap_snprintf(message, PCAP_ERRBUF_SIZE, "%s failed with error %d: %s", str, val, string);
  67. SOCK_DEBUG_MESSAGE(message);
  68. }
  69. void WINAPI svc_control_handler(DWORD Opcode)
  70. {
  71. switch(Opcode)
  72. {
  73. case SERVICE_CONTROL_STOP:
  74. //
  75. // XXX - is this sufficient to clean up the service?
  76. // To be really honest, only the main socket and
  77. // such these stuffs are cleared; however the threads
  78. // that are running are not stopped.
  79. // This can be seen by placing a breakpoint at the
  80. // end of svc_main(), in which you will see that is
  81. // never reached. However, as soon as you set the
  82. // service status to "stopped", the
  83. // StartServiceCtrlDispatcher() returns and the main
  84. // thread ends. Then, Win32 has a good automatic
  85. // cleanup, so that all the threads which are still
  86. // running are stopped when the main thread ends.
  87. //
  88. send_shutdown_notification();
  89. update_svc_status(SERVICE_STOP_PENDING, 0);
  90. break;
  91. /*
  92. Pause and Continue have an usual meaning and they are used just to be able
  93. to change the running parameters at run-time. In other words, they act
  94. like the SIGHUP signal on UNIX. All the running threads continue to run and
  95. they are not paused at all.
  96. Particularly,
  97. - PAUSE does nothing
  98. - CONTINUE re-reads the configuration file and creates the new threads that
  99. can be needed according to the new configuration.
  100. */
  101. case SERVICE_CONTROL_PAUSE:
  102. update_svc_status(SERVICE_PAUSED, 0);
  103. break;
  104. case SERVICE_CONTROL_CONTINUE:
  105. update_svc_status(SERVICE_RUNNING, 0);
  106. //
  107. // Tell the main loop to re-read the configuration.
  108. //
  109. send_reread_configuration_notification();
  110. break;
  111. case SERVICE_CONTROL_INTERROGATE:
  112. // Fall through to send current status.
  113. // WARNING: not implemented
  114. update_svc_status(SERVICE_RUNNING, 0);
  115. MessageBox(NULL, "Not implemented", "warning", MB_OK);
  116. break;
  117. case SERVICE_CONTROL_PARAMCHANGE:
  118. //
  119. // Tell the main loop to re-read the configuration.
  120. //
  121. send_reread_configuration_notification();
  122. break;
  123. }
  124. // Send current status.
  125. return;
  126. }
  127. void WINAPI svc_main(DWORD argc, char **argv)
  128. {
  129. service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
  130. if (!service_status_handle)
  131. return;
  132. service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
  133. service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
  134. // | SERVICE_ACCEPT_SHUTDOWN ;
  135. update_svc_status(SERVICE_RUNNING, 0);
  136. //
  137. // Service requests until we're told to stop.
  138. //
  139. main_startup();
  140. //
  141. // It returned, so we were told to stop.
  142. //
  143. update_svc_status(SERVICE_STOPPED, 0);
  144. }
  145. static void
  146. update_svc_status(DWORD state, DWORD progress_indicator)
  147. {
  148. service_status.dwWin32ExitCode = NO_ERROR;
  149. service_status.dwCurrentState = state;
  150. service_status.dwCheckPoint = progress_indicator;
  151. service_status.dwWaitHint = 0;
  152. SetServiceStatus(service_status_handle, &service_status);
  153. }
  154. /*
  155. sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
  156. sc description rpcapd "Allows to capture traffic on this host from a remote machine."
  157. */