ServiceInstaller.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. if (GetModuleFileName(NULL, szPathTmp, ARRAYSIZE(szPath)) == 0)
  54. {
  55. ret = "GetModuleFileName failed, unable to get path to self";
  56. goto Cleanup;
  57. }
  58. // Quote path in case it contains spaces
  59. _snprintf_s(szPath,sizeof(szPath),"\"%s\"",szPathTmp);
  60. // Open the local default service control manager database
  61. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
  62. SC_MANAGER_CREATE_SERVICE);
  63. if (schSCManager == NULL)
  64. {
  65. ret = "OpenSCManager failed";
  66. goto Cleanup;
  67. }
  68. // Install the service into SCM by calling CreateService
  69. schService = CreateService(
  70. schSCManager, // SCManager database
  71. pszServiceName, // Name of service
  72. pszDisplayName, // Name to display
  73. SERVICE_QUERY_STATUS, // Desired access
  74. SERVICE_WIN32_OWN_PROCESS, // Service type
  75. dwStartType, // Service start type
  76. SERVICE_ERROR_NORMAL, // Error control type
  77. szPath, // Service's binary
  78. NULL, // No load ordering group
  79. NULL, // No tag identifier
  80. pszDependencies, // Dependencies
  81. pszAccount, // Service running account
  82. pszPassword // Password of the account
  83. );
  84. if (schService == NULL)
  85. {
  86. ret = "CreateService failed";
  87. goto Cleanup;
  88. }
  89. Cleanup:
  90. // Centralized cleanup for all allocated resources.
  91. if (schSCManager)
  92. {
  93. CloseServiceHandle(schSCManager);
  94. schSCManager = NULL;
  95. }
  96. if (schService)
  97. {
  98. CloseServiceHandle(schService);
  99. schService = NULL;
  100. }
  101. return ret;
  102. }
  103. //
  104. // FUNCTION: UninstallService
  105. //
  106. // PURPOSE: Stop and remove the service from the local service control
  107. // manager database.
  108. //
  109. // PARAMETERS:
  110. // * pszServiceName - the name of the service to be removed.
  111. //
  112. // NOTE: If the function fails to uninstall the service, it prints the
  113. // error in the standard output stream for users to diagnose the problem.
  114. //
  115. std::string UninstallService(PSTR pszServiceName)
  116. {
  117. std::string ret;
  118. SC_HANDLE schSCManager = NULL;
  119. SC_HANDLE schService = NULL;
  120. SERVICE_STATUS ssSvcStatus = {};
  121. // Open the local default service control manager database
  122. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  123. if (schSCManager == NULL)
  124. {
  125. ret = "OpenSCManager failed";
  126. goto Cleanup;
  127. }
  128. // Open the service with delete, stop, and query status permissions
  129. schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
  130. SERVICE_QUERY_STATUS | DELETE);
  131. if (schService == NULL)
  132. {
  133. ret = "OpenService failed (is service installed?)";
  134. goto Cleanup;
  135. }
  136. // Try to stop the service
  137. if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
  138. {
  139. Sleep(500);
  140. while (QueryServiceStatus(schService, &ssSvcStatus))
  141. {
  142. if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
  143. {
  144. Sleep(500);
  145. }
  146. else break;
  147. }
  148. }
  149. // Now remove the service by calling DeleteService.
  150. if (!DeleteService(schService))
  151. {
  152. ret = "DeleteService failed (is service running?)";
  153. goto Cleanup;
  154. }
  155. Cleanup:
  156. // Centralized cleanup for all allocated resources.
  157. if (schSCManager)
  158. {
  159. CloseServiceHandle(schSCManager);
  160. schSCManager = NULL;
  161. }
  162. if (schService)
  163. {
  164. CloseServiceHandle(schService);
  165. schService = NULL;
  166. }
  167. return ret;
  168. }