Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
9.1 KiB

  1. // NTService.cpp
  2. //
  3. // Implementation of CNTService
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include "NTService.h"
  7. #include "svchost.h"
  8. #include "PMSPService.h"
  9. #include <crtdbg.h>
  10. //// static variables
  11. CNTService* g_pService = NULL;
  12. CRITICAL_SECTION g_csLock;
  13. CNTService::CNTService()
  14. {
  15. // // Set the default service name and version
  16. // strncpy(m_szServiceName, szServiceName, sizeof(m_szServiceName)-1);
  17. // strncpy(m_szServiceDisplayName, szServiceDisplayName, sizeof(m_szServiceDisplayName)-1);
  18. // m_iMajorVersion = 1;
  19. // m_iMinorVersion = 4;
  20. // set up the initial service status
  21. m_hServiceStatus = NULL;
  22. m_Status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  23. m_Status.dwCurrentState = SERVICE_STOPPED;
  24. m_Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  25. m_Status.dwWin32ExitCode = 0;
  26. m_Status.dwServiceSpecificExitCode = 0;
  27. m_Status.dwCheckPoint = 0;
  28. m_Status.dwWaitHint = 0;
  29. m_bIsRunning = FALSE;
  30. }
  31. CNTService::~CNTService()
  32. {
  33. DebugMsg("CNTService::~CNTService()");
  34. }
  35. ////////////////////////////////////////////////////////////////////////////////////////
  36. // Default command line argument parsing
  37. ////////////////////////////////////////////////////////////////////////////////////////
  38. // Install/uninstall routines
  39. // Test if the service is currently installed
  40. BOOL CNTService::IsInstalled()
  41. {
  42. BOOL bResult = FALSE;
  43. // Open the Service Control Manager
  44. SC_HANDLE hSCM = ::OpenSCManager(NULL, // local machine
  45. NULL, // ServicesActive database
  46. GENERIC_READ); // access combined STANDARD_RIGHTS_READ,
  47. // SC_MANAGER_ENUMERATE_SERVICE, and
  48. // SC_MANAGER_QEURY_LOCK_STATUS
  49. if (hSCM)
  50. {
  51. // Try to open the service
  52. SC_HANDLE hService = ::OpenService(hSCM,
  53. SERVICE_NAME,
  54. SERVICE_QUERY_CONFIG);
  55. if (hService)
  56. {
  57. bResult = TRUE;
  58. ::CloseServiceHandle(hService);
  59. }
  60. ::CloseServiceHandle(hSCM);
  61. }
  62. return bResult;
  63. }
  64. ///////////////////////////////////////////////////////////////////////////////////////
  65. // Logging functions
  66. // This function makes an entry into the application event log
  67. void CNTService::LogEvent(WORD wType, DWORD dwID,
  68. const char* pszS1,
  69. const char* pszS2,
  70. const char* pszS3)
  71. {
  72. HANDLE hEventSource = NULL;
  73. const char* ps[3];
  74. ps[0] = pszS1;
  75. ps[1] = pszS2;
  76. ps[2] = pszS3;
  77. WORD iStr = 0;
  78. for (int i = 0; i < 3; i++) {
  79. if (ps[i] != NULL) iStr++;
  80. else
  81. {
  82. // Ensure that the remaining arguments are NULL, zap them
  83. // if they are not. Otherwise, ReportEvent will fail
  84. for (; i < 3; i++)
  85. {
  86. if (ps[i] != NULL)
  87. {
  88. _ASSERTE(ps[i] == NULL);
  89. ps[i] = NULL;
  90. }
  91. }
  92. // We will break out of the outer for loop since i == 3
  93. }
  94. }
  95. // Register event source
  96. hEventSource = ::RegisterEventSource( NULL, // local machine
  97. SERVICE_NAME); // source name
  98. if (hEventSource)
  99. {
  100. ::ReportEvent(hEventSource,
  101. wType,
  102. 0,
  103. dwID,
  104. NULL, // sid
  105. iStr,
  106. 0,
  107. ps,
  108. NULL);
  109. ::DeregisterEventSource(hEventSource);
  110. }
  111. }
  112. ///////////////////////////////////////////////////////////////////////////////////////////
  113. // status functions
  114. void CNTService::SetStatus(DWORD dwState)
  115. {
  116. DebugMsg("CNTService::SetStatus(%lu, %lu)", m_hServiceStatus, dwState);
  117. // If a stop is pending, the only next state we'll report is STOPPED.
  118. // If the Stop was issued while we are being started, the service thread
  119. // will start fully and then commence stopping (as the code is currently
  120. // structured). While it is starting, it will update the check point.
  121. // We ignore the state it sends in (START_PENDING) and lie to the SCM.
  122. if (m_Status.dwCurrentState != SERVICE_STOP_PENDING ||
  123. dwState == SERVICE_STOPPED)
  124. {
  125. if (m_Status.dwCurrentState != dwState)
  126. {
  127. m_Status.dwCurrentState = dwState;
  128. m_Status.dwCheckPoint = 0;
  129. m_Status.dwWaitHint = 0;
  130. }
  131. }
  132. if (m_Status.dwCurrentState == SERVICE_STOP_PENDING ||
  133. m_Status.dwCurrentState == SERVICE_START_PENDING ||
  134. m_Status.dwCurrentState == SERVICE_PAUSE_PENDING ||
  135. m_Status.dwCurrentState == SERVICE_CONTINUE_PENDING)
  136. {
  137. m_Status.dwCheckPoint++;
  138. m_Status.dwWaitHint = 500;
  139. }
  140. ::SetServiceStatus(m_hServiceStatus, &m_Status);
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////////////////
  143. // Service initialization
  144. BOOL CNTService::Initialize()
  145. {
  146. DWORD dwLastError;
  147. DebugMsg("Entering CNTService::Initialize()");
  148. // Perform the actual initialization
  149. BOOL bResult = OnInit(dwLastError);
  150. // Bump up the check point
  151. SetStatus(SERVICE_START_PENDING);
  152. if (!bResult)
  153. {
  154. m_Status.dwWin32ExitCode = dwLastError;
  155. CNTService::DebugMsg("The initialization process failed" );
  156. return FALSE;
  157. }
  158. DebugMsg("Leaving CNTService::Initialize()");
  159. return TRUE;
  160. }
  161. ///////////////////////////////////////////////////////////////////////////////////////////////
  162. // main function to do the real work of the service
  163. //////////////////////////////////////////////////////////////////////////////////////
  164. // Control request handlers
  165. // static member function (callback) to handle commands from the
  166. // service control manager
  167. void CNTService::Handler(DWORD dwOpcode)
  168. {
  169. BOOL bStop = FALSE;
  170. __try
  171. {
  172. EnterCriticalSection (&g_csLock);
  173. // Get a pointer to the object
  174. CNTService* pService = g_pService;
  175. if (!pService)
  176. {
  177. __leave;
  178. }
  179. CNTService::DebugMsg("CNTService::Handler(%lu)", dwOpcode);
  180. switch (dwOpcode) {
  181. case SERVICE_CONTROL_STOP: // 1
  182. pService->OnStop();
  183. break;
  184. case SERVICE_CONTROL_PAUSE: // 2
  185. pService->OnPause();
  186. break;
  187. case SERVICE_CONTROL_CONTINUE: // 3
  188. pService->OnContinue();
  189. break;
  190. case SERVICE_CONTROL_INTERROGATE: // 4
  191. pService->OnInterrogate();
  192. break;
  193. case SERVICE_CONTROL_SHUTDOWN: // 5
  194. pService->OnShutdown();
  195. break;
  196. default:
  197. if (dwOpcode >= SERVICE_CONTROL_USER)
  198. {
  199. if (!pService->OnUserControl(dwOpcode))
  200. {
  201. pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST);
  202. }
  203. }
  204. else
  205. {
  206. pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST);
  207. }
  208. break;
  209. }
  210. // Report current status - let the On* functions do this by calling SetStatus
  211. // CNTService::DebugMsg("Updating status (%lu, %lu)",
  212. // pService->m_hServiceStatus,
  213. // pService->m_Status.dwCurrentState);
  214. // ::SetServiceStatus(pService->m_hServiceStatus, &pService->m_Status);
  215. }
  216. __finally
  217. {
  218. LeaveCriticalSection (&g_csLock);
  219. }
  220. }
  221. // called when the service is interrogated
  222. void CNTService::OnInterrogate()
  223. {
  224. DebugMsg("CNTService::OnInterrogate()");
  225. }
  226. // called when the service is paused
  227. void CNTService::OnPause()
  228. {
  229. DebugMsg("CNTService::OnPause()");
  230. }
  231. // called when the service is continued
  232. void CNTService::OnContinue()
  233. {
  234. DebugMsg("CNTService::OnContinue()");
  235. }
  236. // called when the service is shut down
  237. void CNTService::OnShutdown()
  238. {
  239. DebugMsg("CNTService::OnShutdown()");
  240. }
  241. ////////////////////////////////////////////////////////////////////////////////////////////
  242. // Debugging support
  243. // #define WRITE_TO_LOG_FILE
  244. void CNTService::DebugMsg(const char* pszFormat, ...)
  245. {
  246. #if defined(DBG) || defined(WRITE_TO_LOG_FILE)
  247. char buf[1024];
  248. sprintf(buf, "[Serial Number Library](%lu): ", GetCurrentThreadId());
  249. va_list arglist;
  250. va_start(arglist, pszFormat);
  251. vsprintf(&buf[strlen(buf)], pszFormat, arglist);
  252. va_end(arglist);
  253. strcat(buf, "\n");
  254. #if defined(DBG)
  255. OutputDebugString(buf);
  256. #endif
  257. #if defined(WRITE_TO_LOG_FILE)
  258. FILE* fp = fopen("c:\\WmdmService.txt", "a");
  259. if (fp)
  260. {
  261. fprintf(fp, buf);
  262. fclose(fp);
  263. }
  264. #endif
  265. #endif
  266. }