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.

501 lines
12 KiB

  1. //
  2. // MODULE: LaunchServ.cpp
  3. //
  4. // PURPOSE: Implementation of WinMain.
  5. //
  6. // PROJECT: Local Troubleshooter Launcher for the Device Manager
  7. //
  8. // COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
  9. //
  10. // AUTHOR: Richard Meadows
  11. //
  12. // ORIGINAL DATE: 2-26-98
  13. //
  14. // NOTES:
  15. // 1. 90% of this file was wrote by the ATL wizzard.
  16. // 2. This project is working fine without the proxy/stub dll.
  17. // The interfaces are using the IDispatch interface.
  18. //
  19. // Version Date By Comments
  20. //--------------------------------------------------------------------
  21. // V0.1 - RM Original
  22. ///////////////////////
  23. // ATL Wizzard Note:
  24. //
  25. // Note: Proxy/Stub Information
  26. // To build a separate proxy/stub DLL,
  27. // run nmake -f LaunchServps.mk in the project directory.
  28. //
  29. #include "stdafx.h"
  30. #include "resource.h"
  31. #include "initguid.h"
  32. #include "LaunchServ.h"
  33. #include "LaunchServ_i.c"
  34. #include "StateInfo.h"
  35. #include "RSSTACK.h"
  36. #include "TSLError.h"
  37. #include "TSMapAbstract.h"
  38. #include "TSMap.h"
  39. #include "TSMapClient.h"
  40. #include "Launch.h"
  41. #include <stdio.h>
  42. #include "LaunchTS.h"
  43. #include "TShootATL.h"
  44. CServiceModule _Module;
  45. CSMStateInfo g_StateInfo;
  46. BEGIN_OBJECT_MAP(ObjectMap)
  47. OBJECT_ENTRY(CLSID_LaunchTS, CLaunchTS)
  48. OBJECT_ENTRY(CLSID_TShootATL, CTShootATL)
  49. END_OBJECT_MAP()
  50. LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
  51. {
  52. while (*p1 != NULL)
  53. {
  54. LPCTSTR p = p2;
  55. while (*p != NULL)
  56. {
  57. if (*p1 == *p++)
  58. return p1+1;
  59. }
  60. p1++;
  61. }
  62. return NULL;
  63. }
  64. // Although some of these functions are big they are declared inline since they are only used once
  65. inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib, BOOL bService)
  66. {
  67. HRESULT hr = CoInitialize(NULL);
  68. if (FAILED(hr))
  69. return hr;
  70. // Remove any previous service since it may point to
  71. // the incorrect file
  72. Uninstall();
  73. // Add service entries
  74. UpdateRegistryFromResource(IDR_LaunchServ, TRUE);
  75. // Adjust the AppID for Local Server or Service
  76. CRegKey keyAppID;
  77. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"));
  78. if (lRes != ERROR_SUCCESS)
  79. return lRes;
  80. CRegKey key;
  81. lRes = key.Open(keyAppID, _T("{131CC292-7634-11D1-8B6B-0060089BD8C4}"));
  82. if (lRes != ERROR_SUCCESS)
  83. return lRes;
  84. key.DeleteValue(_T("LocalService"));
  85. if (bService)
  86. {
  87. key.SetValue(_T("LaunchServ"), _T("LocalService"));
  88. key.SetValue(_T("-Service"), _T("ServiceParameters"));
  89. // Create service
  90. Install();
  91. }
  92. // Add object entries
  93. hr = CComModule::RegisterServer(bRegTypeLib);
  94. CoUninitialize();
  95. return hr;
  96. }
  97. inline HRESULT CServiceModule::UnregisterServer()
  98. {
  99. HRESULT hr = CoInitialize(NULL);
  100. if (FAILED(hr))
  101. return hr;
  102. // Remove service entries
  103. UpdateRegistryFromResource(IDR_LaunchServ, FALSE);
  104. // Remove service
  105. Uninstall();
  106. // Remove object entries
  107. CComModule::UnregisterServer();
  108. CoUninitialize();
  109. return S_OK;
  110. }
  111. inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID)
  112. {
  113. CComModule::Init(p, h);
  114. m_bService = TRUE;
  115. LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
  116. // set up the initial service status
  117. m_hServiceStatus = NULL;
  118. m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  119. m_status.dwCurrentState = SERVICE_STOPPED;
  120. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  121. m_status.dwWin32ExitCode = 0;
  122. m_status.dwServiceSpecificExitCode = 0;
  123. m_status.dwCheckPoint = 0;
  124. m_status.dwWaitHint = 0;
  125. }
  126. LONG CServiceModule::Unlock()
  127. {
  128. LONG l = CComModule::Unlock();
  129. if (l == 0 && !m_bService)
  130. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  131. return l;
  132. }
  133. BOOL CServiceModule::IsInstalled()
  134. {
  135. BOOL bResult = FALSE;
  136. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  137. if (hSCM != NULL)
  138. {
  139. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
  140. if (hService != NULL)
  141. {
  142. bResult = TRUE;
  143. ::CloseServiceHandle(hService);
  144. }
  145. ::CloseServiceHandle(hSCM);
  146. }
  147. return bResult;
  148. }
  149. inline BOOL CServiceModule::Install()
  150. {
  151. if (IsInstalled())
  152. return TRUE;
  153. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  154. if (hSCM == NULL)
  155. {
  156. MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  157. return FALSE;
  158. }
  159. // Get the executable file path
  160. TCHAR szFilePath[_MAX_PATH];
  161. ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  162. SC_HANDLE hService = ::CreateService(
  163. hSCM, m_szServiceName, m_szServiceName,
  164. SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  165. SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
  166. szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
  167. if (hService == NULL)
  168. {
  169. ::CloseServiceHandle(hSCM);
  170. MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
  171. return FALSE;
  172. }
  173. ::CloseServiceHandle(hService);
  174. ::CloseServiceHandle(hSCM);
  175. return TRUE;
  176. }
  177. inline BOOL CServiceModule::Uninstall()
  178. {
  179. if (!IsInstalled())
  180. return TRUE;
  181. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  182. if (hSCM == NULL)
  183. {
  184. MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  185. return FALSE;
  186. }
  187. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);
  188. if (hService == NULL)
  189. {
  190. ::CloseServiceHandle(hSCM);
  191. MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
  192. return FALSE;
  193. }
  194. SERVICE_STATUS status;
  195. ::ControlService(hService, SERVICE_CONTROL_STOP, &status);
  196. BOOL bDelete = ::DeleteService(hService);
  197. ::CloseServiceHandle(hService);
  198. ::CloseServiceHandle(hSCM);
  199. if (bDelete)
  200. return TRUE;
  201. MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
  202. return FALSE;
  203. }
  204. ///////////////////////////////////////////////////////////////////////////////////////
  205. // Logging functions
  206. void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
  207. {
  208. TCHAR chMsg[256];
  209. HANDLE hEventSource;
  210. LPTSTR lpszStrings[1];
  211. va_list pArg;
  212. va_start(pArg, pFormat);
  213. _vstprintf(chMsg, pFormat, pArg);
  214. va_end(pArg);
  215. lpszStrings[0] = chMsg;
  216. if (m_bService)
  217. {
  218. /* Get a handle to use with ReportEvent(). */
  219. hEventSource = RegisterEventSource(NULL, m_szServiceName);
  220. if (hEventSource != NULL)
  221. {
  222. /* Write to event log. */
  223. ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
  224. DeregisterEventSource(hEventSource);
  225. }
  226. }
  227. else
  228. {
  229. // As we are not running as a service, just write the error to the console.
  230. _putts(chMsg);
  231. }
  232. }
  233. //////////////////////////////////////////////////////////////////////////////////////////////
  234. // Service startup and registration
  235. inline void CServiceModule::Start()
  236. {
  237. SERVICE_TABLE_ENTRY st[] =
  238. {
  239. { m_szServiceName, _ServiceMain },
  240. { NULL, NULL }
  241. };
  242. if (m_bService && !::StartServiceCtrlDispatcher(st))
  243. {
  244. m_bService = FALSE;
  245. }
  246. if (m_bService == FALSE)
  247. Run();
  248. }
  249. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  250. {
  251. // Register the control request handler
  252. m_status.dwCurrentState = SERVICE_START_PENDING;
  253. m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
  254. if (m_hServiceStatus == NULL)
  255. {
  256. LogEvent(_T("Handler not installed"));
  257. return;
  258. }
  259. SetServiceStatus(SERVICE_START_PENDING);
  260. m_status.dwWin32ExitCode = S_OK;
  261. m_status.dwCheckPoint = 0;
  262. m_status.dwWaitHint = 0;
  263. // When the Run function returns, the service has stopped.
  264. Run();
  265. SetServiceStatus(SERVICE_STOPPED);
  266. LogEvent(_T("Service stopped"));
  267. }
  268. inline void CServiceModule::Handler(DWORD dwOpcode)
  269. {
  270. switch (dwOpcode)
  271. {
  272. case SERVICE_CONTROL_STOP:
  273. SetServiceStatus(SERVICE_STOP_PENDING);
  274. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  275. break;
  276. case SERVICE_CONTROL_PAUSE:
  277. break;
  278. case SERVICE_CONTROL_CONTINUE:
  279. break;
  280. case SERVICE_CONTROL_INTERROGATE:
  281. break;
  282. case SERVICE_CONTROL_SHUTDOWN:
  283. break;
  284. default:
  285. LogEvent(_T("Bad service request"));
  286. }
  287. }
  288. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  289. {
  290. _Module.ServiceMain(dwArgc, lpszArgv);
  291. }
  292. void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
  293. {
  294. _Module.Handler(dwOpcode);
  295. }
  296. void CServiceModule::SetServiceStatus(DWORD dwState)
  297. {
  298. m_status.dwCurrentState = dwState;
  299. ::SetServiceStatus(m_hServiceStatus, &m_status);
  300. }
  301. void CServiceModule::Run()
  302. {
  303. HRESULT hr;
  304. _Module.dwThreadID = GetCurrentThreadId();
  305. // HRESULT hRes = CoInitialize(NULL);
  306. // If you are running on NT 4.0 or higher you can use the following call
  307. // instead to make the EXE free threaded.
  308. // This means that calls come in on a random RPC thread
  309. HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  310. _ASSERTE(SUCCEEDED(hr));
  311. // This provides a NULL DACL which will allow access to everyone.
  312. CSecurityDescriptor sd;
  313. sd.InitializeFromThreadToken();
  314. hr = CoInitializeSecurity(sd, -1, NULL, NULL,
  315. RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
  316. _ASSERTE(SUCCEEDED(hr));
  317. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  318. _ASSERTE(SUCCEEDED(hr));
  319. LogEvent(_T("Service started"));
  320. SetServiceStatus(SERVICE_RUNNING);
  321. MSG msg;
  322. while (GetMessage(&msg, 0, 0, 0))
  323. DispatchMessage(&msg);
  324. _Module.RevokeClassObjects();
  325. CoUninitialize();
  326. }
  327. /////////////////////////////////////////////////////////////////////////////
  328. //
  329. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  330. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  331. {
  332. lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  333. _Module.Init(ObjectMap, hInstance, IDS_SERVICENAME);
  334. _Module.m_bService = TRUE;
  335. TCHAR szTokens[] = _T("-/");
  336. LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
  337. HRESULT hRes;
  338. TCHAR szMsg[50];
  339. bool bRegAttempt = false;
  340. bool bShowUsage = false;
  341. bool bSilent = false;
  342. while (lpszToken != NULL)
  343. {
  344. if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
  345. {
  346. bRegAttempt = true;
  347. _tcscpy(szMsg, _T("UnregServer "));
  348. hRes = _Module.UnregisterServer();
  349. }
  350. else if (lstrcmpi(lpszToken, _T("RegServer"))==0) // Register as Local Server
  351. {
  352. bRegAttempt = true;
  353. _tcscpy(szMsg, _T("RegServer "));
  354. hRes = _Module.RegisterServer(TRUE, FALSE);
  355. }
  356. else if (lstrcmpi(lpszToken, _T("Service"))==0) // Register as Service
  357. {
  358. bRegAttempt = true;
  359. _tcscpy(szMsg, _T("Service "));
  360. hRes = _Module.RegisterServer(TRUE, TRUE);
  361. }
  362. else if (lstrcmpi(lpszToken, _T("?"))==0)
  363. {
  364. bShowUsage = true;
  365. }
  366. else if (lstrcmpi(lpszToken, _T("h"))==0)
  367. {
  368. bShowUsage = true;
  369. }
  370. else if (_tcsncmp(lpszToken, _T("s"), 1)==0)
  371. {
  372. bSilent = true;
  373. }
  374. else if (_tcsncmp(lpszToken, _T("S"), 1)==0)
  375. {
  376. bSilent = true;
  377. }
  378. lpszToken = FindOneOf(lpszToken, szTokens);
  379. }
  380. if (true == bRegAttempt)
  381. {
  382. if (!FAILED(hRes) && false == bSilent)
  383. {
  384. _tcscat(szMsg, _T("Succeded"));
  385. MessageBox(NULL, szMsg, _Module.m_szServiceName, MB_OK | MB_ICONINFORMATION);
  386. return hRes;
  387. }
  388. else if (false == bSilent)
  389. {
  390. _tcscat(szMsg, _T("Failed"));
  391. MessageBox(NULL, szMsg, _Module.m_szServiceName, MB_OK | MB_ICONEXCLAMATION);
  392. return hRes;
  393. }
  394. else
  395. {
  396. return hRes;
  397. }
  398. }
  399. if (true == bShowUsage)
  400. {
  401. MessageBox(NULL, _T("Usage: <[/UnregServer] [/RegServer] [/Service]>"),
  402. _Module.m_szServiceName, MB_OK | MB_ICONINFORMATION);
  403. return S_OK;
  404. }
  405. // Are we Service or Local Server
  406. CRegKey keyAppID;
  407. LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"));
  408. if (lRes != ERROR_SUCCESS)
  409. return lRes;
  410. CRegKey key;
  411. lRes = key.Open(keyAppID, _T("{131CC292-7634-11D1-8B6B-0060089BD8C4}"));
  412. if (lRes != ERROR_SUCCESS)
  413. return lRes;
  414. TCHAR szValue[_MAX_PATH];
  415. DWORD dwLen = _MAX_PATH;
  416. lRes = key.QueryValue(szValue, _T("LocalService"), &dwLen);
  417. _Module.m_bService = FALSE;
  418. if (lRes == ERROR_SUCCESS)
  419. _Module.m_bService = TRUE;
  420. _Module.Start();
  421. // When we get here, the service has been stopped
  422. return _Module.m_status.dwWin32ExitCode;
  423. }