ServiceInstaller.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /****************************** Module Header ******************************\
  2. * Module Name: ServiceInstaller.cpp
  3. * Project: CppWindowsService
  4. * Copyright (c) Microsoft Corporation.
  5. *
  6. * The file implements functions that install and uninstall the service.
  7. *
  8. * This source is subject to the Microsoft Public License.
  9. * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
  10. * All other rights reserved.
  11. *
  12. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  13. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  15. \***************************************************************************/
  16. #pragma region "Includes"
  17. #include <stdio.h>
  18. #include <windows.h>
  19. #include "ServiceInstaller.h"
  20. #pragma endregion
  21. //
  22. // FUNCTION: InstallService
  23. //
  24. // PURPOSE: Install the current application as a service to the local
  25. // service control manager database.
  26. //
  27. // PARAMETERS:
  28. // * pszServiceName - the name of the service to be installed
  29. // * pszDisplayName - the display name of the service
  30. // * dwStartType - the service start option. This parameter can be one of
  31. // the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
  32. // SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
  33. // * pszDependencies - a pointer to a double null-terminated array of null-
  34. // separated names of services or load ordering groups that the system
  35. // must start before this service.
  36. // * pszAccount - the name of the account under which the service runs.
  37. // * pszPassword - the password to the account name.
  38. //
  39. // NOTE: If the function fails to install the service, it prints the error
  40. // in the standard output stream for users to diagnose the problem.
  41. //
  42. std::string InstallService(PSTR pszServiceName,
  43. PSTR pszDisplayName,
  44. DWORD dwStartType,
  45. PSTR pszDependencies,
  46. PSTR pszAccount,
  47. PSTR pszPassword)
  48. {
  49. std::string ret;
  50. char szPathTmp[MAX_PATH],szPath[MAX_PATH];
  51. SC_HANDLE schSCManager = NULL;
  52. SC_HANDLE schService = NULL;
  53. SERVICE_DESCRIPTION sd;
  54. LPTSTR szDesc = TEXT("Provides secure encrypted communications between hosts over an insecure networks.");
  55. if (GetModuleFileName(NULL, szPathTmp, ARRAYSIZE(szPath)) == 0)
  56. {
  57. ret = "GetModuleFileName failed, unable to get path to self";
  58. goto Cleanup;
  59. }
  60. // Quote path in case it contains spaces
  61. _snprintf_s(szPath,sizeof(szPath),"\"%s\"",szPathTmp);
  62. // Open the local default service control manager database
  63. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
  64. SC_MANAGER_CREATE_SERVICE);
  65. if (schSCManager == NULL)
  66. {
  67. ret = "OpenSCManager failed";
  68. goto Cleanup;
  69. }
  70. // Install the service into SCM by calling CreateService
  71. schService = CreateService(
  72. schSCManager, // SCManager database
  73. pszServiceName, // Name of service
  74. pszDisplayName, // Name to display
  75. SERVICE_ALL_ACCESS, // Desired access
  76. SERVICE_WIN32_OWN_PROCESS, // Service type
  77. dwStartType, // Service start type
  78. SERVICE_ERROR_NORMAL, // Error control type
  79. szPath, // Service's binary
  80. NULL, // No load ordering group
  81. NULL, // No tag identifier
  82. pszDependencies, // Dependencies
  83. pszAccount, // Service running account
  84. pszPassword // Password of the account
  85. );
  86. if (schService == NULL)
  87. {
  88. ret = "CreateService failed";
  89. goto Cleanup;
  90. }
  91. // Setup service description
  92. sd.lpDescription = szDesc;
  93. if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sd)) {
  94. ret = "CreateService failed (description)";
  95. }
  96. Cleanup:
  97. // Centralized cleanup for all allocated resources.
  98. if (schSCManager)
  99. {
  100. CloseServiceHandle(schSCManager);
  101. schSCManager = NULL;
  102. }
  103. if (schService)
  104. {
  105. CloseServiceHandle(schService);
  106. schService = NULL;
  107. }
  108. return ret;
  109. }
  110. //
  111. // FUNCTION: UninstallService
  112. //
  113. // PURPOSE: Stop and remove the service from the local service control
  114. // manager database.
  115. //
  116. // PARAMETERS:
  117. // * pszServiceName - the name of the service to be removed.
  118. //
  119. // NOTE: If the function fails to uninstall the service, it prints the
  120. // error in the standard output stream for users to diagnose the problem.
  121. //
  122. std::string UninstallService(PSTR pszServiceName)
  123. {
  124. std::string ret;
  125. SC_HANDLE schSCManager = NULL;
  126. SC_HANDLE schService = NULL;
  127. SERVICE_STATUS ssSvcStatus = {};
  128. // Open the local default service control manager database
  129. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  130. if (schSCManager == NULL)
  131. {
  132. ret = "OpenSCManager failed";
  133. goto Cleanup;
  134. }
  135. // Open the service with delete, stop, and query status permissions
  136. schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
  137. SERVICE_QUERY_STATUS | DELETE);
  138. if (schService == NULL)
  139. {
  140. ret = "OpenService failed (is service installed?)";
  141. goto Cleanup;
  142. }
  143. // Try to stop the service
  144. if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
  145. {
  146. Sleep(500);
  147. while (QueryServiceStatus(schService, &ssSvcStatus))
  148. {
  149. if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
  150. {
  151. Sleep(500);
  152. }
  153. else break;
  154. }
  155. }
  156. // Now remove the service by calling DeleteService.
  157. if (!DeleteService(schService))
  158. {
  159. ret = "DeleteService failed (is service running?)";
  160. goto Cleanup;
  161. }
  162. Cleanup:
  163. // Centralized cleanup for all allocated resources.
  164. if (schSCManager)
  165. {
  166. CloseServiceHandle(schSCManager);
  167. schSCManager = NULL;
  168. }
  169. if (schService)
  170. {
  171. CloseServiceHandle(schService);
  172. schService = NULL;
  173. }
  174. return ret;
  175. }