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.

2345 lines
77 KiB

  1. #include "stdafx.h"
  2. #include <winsvc.h>
  3. #include <winsock2.h>
  4. #include <nspapi.h>
  5. #include "w3svc.h"
  6. #include <inetsvcs.h>
  7. #include <pwsdata.hxx>
  8. #include "kill.h"
  9. #include "svc.h"
  10. TCHAR gServicesWhichMustBeRestarted[20][PROCESS_SIZE];
  11. int gServicesWhichMustBeRestarted_nextuse = 0;
  12. int gServicesWhichMustBeRestarted_total = 0;
  13. extern int g_GlobalDebugLevelFlag;
  14. int ServicesRestartList_EntryExists(LPCTSTR szServiceName)
  15. {
  16. int iFoundMatch = FALSE;
  17. // loop thru the whole list
  18. for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
  19. {
  20. if (_tcsicmp(gServicesWhichMustBeRestarted[i], szServiceName) == 0)
  21. {
  22. iFoundMatch = TRUE;
  23. break;
  24. }
  25. }
  26. return iFoundMatch;
  27. }
  28. int ServicesRestartList_Add(LPCTSTR szServiceName)
  29. {
  30. // check if this value already exists in the globalarary
  31. if (ServicesRestartList_EntryExists(szServiceName)) {return FALSE;}
  32. // move info into global array
  33. if (gServicesWhichMustBeRestarted_nextuse <= 20)
  34. {
  35. _tcscpy(gServicesWhichMustBeRestarted[gServicesWhichMustBeRestarted_nextuse],szServiceName);
  36. // increment counter to array
  37. // increment next use space
  38. ++gServicesWhichMustBeRestarted_total;
  39. ++gServicesWhichMustBeRestarted_nextuse;
  40. }
  41. return TRUE;
  42. }
  43. int ServicesRestartList_RestartServices(void)
  44. {
  45. int iReturn = FALSE;
  46. INT err = 0;
  47. // loop thru the whole list and restart the services in reverse
  48. // order from how they were entered?
  49. if (gServicesWhichMustBeRestarted_total >= 1)
  50. {
  51. iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices()Start.\n")));
  52. for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
  53. {
  54. if (CheckifServiceExist(gServicesWhichMustBeRestarted[i]) == 0 )
  55. {
  56. err = InetStartService(gServicesWhichMustBeRestarted[i]);
  57. }
  58. else
  59. {
  60. iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices():%s:Not restarting since it no longer exist.\n"),gServicesWhichMustBeRestarted[i]));
  61. }
  62. }
  63. iisDebugOut_End(_T("RestartServices"));
  64. }
  65. return iReturn;
  66. }
  67. DWORD InetStopExtraWait(LPCTSTR lpServiceName)
  68. {
  69. DWORD dwSvcMaxSleep = 180000;
  70. int iFileExist = FALSE;
  71. // Wait. How long should we really wait for this service to actually stop?
  72. // the iisadmin Service can take a long time if the metabase.bin file is huge.
  73. // So... if it's the iisadmin service we're trying to stop, then
  74. // check to see how big the metabase.bin file is, then for each 1meg give it 3 minutes (180000)
  75. if (_tcsicmp(lpServiceName,_T("IISADMIN")) == 0)
  76. {
  77. // look for the metabase.bin file
  78. TCHAR szTempDir[_MAX_PATH];
  79. _tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv);
  80. AddPath(szTempDir, _T("Metabase.bin"));
  81. if (IsFileExist(szTempDir))
  82. {
  83. iFileExist = TRUE;
  84. }
  85. else
  86. {
  87. _tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv);
  88. AddPath(szTempDir, _T("Metabase.xml"));
  89. if (IsFileExist(szTempDir))
  90. {
  91. iFileExist = TRUE;
  92. }
  93. }
  94. if (TRUE == iFileExist)
  95. {
  96. // Check to see how big it is.
  97. DWORD dwFileSize = ReturnFileSize(szTempDir);
  98. if (dwFileSize != 0xFFFFFFFF)
  99. {
  100. int iTime = 1;
  101. // We were able to get the file size.
  102. // for each meg for size, give it 3 minutes to save.
  103. if (dwFileSize > 1000000)
  104. {
  105. iTime = (dwFileSize/1000000);
  106. dwSvcMaxSleep = iTime * 180000;
  107. iisDebugOut((LOG_TYPE_TRACE, _T("InetStopExtraWait():Metabase.bin is kind of big (>1meg), Lets wait longer for IISADMIN service to stop.maxmilsec=0x%x.\n"),dwSvcMaxSleep));
  108. }
  109. }
  110. }
  111. }
  112. return dwSvcMaxSleep;
  113. }
  114. // function: IsServiceDisabled
  115. //
  116. // Check to see if the service being sent in is disabled
  117. BOOL
  118. IsServiceDisabled(LPTSTR szServiceName)
  119. {
  120. SC_HANDLE hService;
  121. SC_HANDLE hSCManager;
  122. BOOL bRet = FALSE;
  123. BUFFER buffConfig;
  124. DWORD dwSizeRequired;
  125. hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
  126. if ( hSCManager == NULL )
  127. {
  128. return FALSE;
  129. }
  130. hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG );
  131. if ( hService == NULL )
  132. {
  133. CloseServiceHandle( hSCManager );
  134. return FALSE;
  135. }
  136. if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) &&
  137. ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
  138. buffConfig.Resize( dwSizeRequired ) &&
  139. QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired )
  140. )
  141. {
  142. // Check the service Startup Type
  143. bRet = ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->dwStartType == SERVICE_DISABLED;
  144. }
  145. CloseServiceHandle( hSCManager );
  146. CloseServiceHandle( hService );
  147. return bRet;
  148. }
  149. // function: SetServiceStart
  150. //
  151. // Change the service state
  152. void
  153. SetServiceStart(LPTSTR szServiceName, DWORD dwServiceStart)
  154. {
  155. SC_HANDLE hService;
  156. SC_HANDLE hSCManager;
  157. hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
  158. if ( hSCManager == NULL )
  159. {
  160. return;
  161. }
  162. hService = OpenService( hSCManager, szServiceName, SERVICE_CHANGE_CONFIG );
  163. if ( hService == NULL )
  164. {
  165. CloseServiceHandle( hSCManager );
  166. return;
  167. }
  168. ChangeServiceConfig( hService,
  169. SERVICE_NO_CHANGE, // ServiceType
  170. dwServiceStart, // Startup
  171. SERVICE_NO_CHANGE, // Error Control
  172. NULL, // Binary Path
  173. NULL, // Load order group
  174. NULL, // TagId
  175. NULL, // Dependencies
  176. NULL, // Service Start Name
  177. NULL, // Password
  178. NULL ); // StartName
  179. CloseServiceHandle( hSCManager );
  180. CloseServiceHandle( hService );
  181. }
  182. INT InetDisableService( LPCTSTR lpServiceName )
  183. {
  184. INT err = 0;
  185. const DWORD dwSvcSleepInterval = 500 ;
  186. DWORD dwSvcMaxSleep = 180000 ;
  187. DWORD dwSleepTotal;
  188. SC_HANDLE hScManager = NULL;
  189. SC_HANDLE hService = NULL;
  190. // Calculcate if this is a "special" service which we
  191. // need to give more time to in order to stop.
  192. dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
  193. do {
  194. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  195. {
  196. err = GetLastError();
  197. break;
  198. }
  199. // if the service is running, stop it
  200. SERVICE_STATUS svcStatus;
  201. if ( QueryServiceStatus( hService, &svcStatus ))
  202. {
  203. if (( svcStatus.dwCurrentState == SERVICE_RUNNING ))
  204. {
  205. if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus ))
  206. {
  207. err = GetLastError();
  208. break;
  209. }
  210. for ( dwSleepTotal = 0 ;
  211. dwSleepTotal < dwSvcMaxSleep
  212. && (QueryServiceStatus( hService, & svcStatus ))
  213. && svcStatus.dwCurrentState == SERVICE_STOP_PENDING ;
  214. dwSleepTotal += dwSvcSleepInterval )
  215. {
  216. ::Sleep( dwSvcSleepInterval ) ;
  217. }
  218. }
  219. }
  220. if ( !ChangeServiceConfig( hService,
  221. SERVICE_NO_CHANGE,
  222. SERVICE_DISABLED,
  223. SERVICE_NO_CHANGE,
  224. NULL,
  225. NULL,
  226. NULL,
  227. NULL,
  228. NULL,
  229. NULL,
  230. NULL ) )
  231. {
  232. err = GetLastError();
  233. }
  234. } while ( FALSE );
  235. if (hService){CloseServiceHandle(hService);}
  236. if (hScManager){CloseServiceHandle(hScManager);}
  237. iisDebugOut((LOG_TYPE_TRACE, _T("InetDisableService():ServiceName=%s. Return=0x%x\n"), lpServiceName, err));
  238. return(err);
  239. }
  240. INT InetStartService( LPCTSTR lpServiceName )
  241. {
  242. iisDebugOut_Start1(_T("InetStartService"),(LPTSTR) lpServiceName);
  243. INT err = 0;
  244. INT err2 = 0;
  245. const DWORD dwSvcSleepInterval = 500 ;
  246. DWORD dwSvcMaxSleep = 180000 ;
  247. SC_HANDLE hScManager = NULL;
  248. SC_HANDLE hService = NULL;
  249. // Calculcate if this is a "special" service which we
  250. // need to give more time to in order to stop.
  251. dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
  252. do
  253. {
  254. // set up the service first
  255. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  256. {
  257. err = GetLastError();
  258. break;
  259. }
  260. SERVICE_STATUS svcStatus;
  261. if ( !QueryServiceStatus( hService, &svcStatus ))
  262. {
  263. err = ::GetLastError();
  264. break;
  265. }
  266. if ( svcStatus.dwCurrentState == SERVICE_RUNNING )
  267. {
  268. // We will only get this ERROR_SERVICE_MARKED_FOR_DELETE
  269. // message if the service is already running.
  270. if ( !::StartService( hService, 0, NULL ))
  271. {
  272. err2 = ::GetLastError();
  273. if (err2 == ERROR_SERVICE_MARKED_FOR_DELETE) {err = err2;}
  274. }
  275. break; // service already started and running
  276. }
  277. if ( !::StartService( hService, 0, NULL ))
  278. {
  279. err = ::GetLastError();
  280. break;
  281. }
  282. // Wait for the service to attain "running" status; but
  283. // wait no more than 3 minute.
  284. DWORD dwSleepTotal;
  285. for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep
  286. && (QueryServiceStatus( hService, &svcStatus ))
  287. && svcStatus.dwCurrentState == SERVICE_START_PENDING ;
  288. dwSleepTotal += dwSvcSleepInterval )
  289. {
  290. ::Sleep( dwSvcSleepInterval ) ;
  291. }
  292. if ( svcStatus.dwCurrentState != SERVICE_RUNNING )
  293. {
  294. err = dwSleepTotal > dwSvcMaxSleep ? ERROR_SERVICE_REQUEST_TIMEOUT : svcStatus.dwWin32ExitCode;
  295. break;
  296. }
  297. } while ( FALSE );
  298. if (hService){CloseServiceHandle(hService);}
  299. if (hScManager){CloseServiceHandle(hScManager);}
  300. if (err){iisDebugOut((LOG_TYPE_WARN, _T("InetStartService():ServiceName=%s unable to start WARNING. Err=0x%x.\n"), lpServiceName, err));}
  301. else{iisDebugOut((LOG_TYPE_TRACE, _T("InetStartService():ServiceName=%s success.\n"), lpServiceName));}
  302. return(err);
  303. }
  304. DWORD InetQueryServiceStatus( LPCTSTR lpServiceName )
  305. {
  306. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s\n"), (LPTSTR) lpServiceName));
  307. DWORD dwStatus = 0;
  308. INT err = 0;
  309. SC_HANDLE hScManager = NULL;
  310. SC_HANDLE hService = NULL;
  311. SERVICE_STATUS svcStatus;
  312. do {
  313. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  314. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ||
  315. !::QueryServiceStatus( hService, &svcStatus ) )
  316. {
  317. err = GetLastError();
  318. break;
  319. }
  320. dwStatus = svcStatus.dwCurrentState;
  321. } while (0);
  322. if (hService){CloseServiceHandle(hService);}
  323. if (hScManager){CloseServiceHandle(hScManager);}
  324. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  325. return( dwStatus );
  326. }
  327. INT InetStopService( LPCTSTR lpServiceName )
  328. {
  329. INT err = 0;
  330. const DWORD dwSvcSleepInterval = 500 ;
  331. DWORD dwSvcMaxSleep = 180000 ;
  332. DWORD dwSleepTotal;
  333. SC_HANDLE hScManager = NULL;
  334. SC_HANDLE hService = NULL;
  335. // Calculcate if this is a "special" service which we
  336. // need to give more time to in order to stop.
  337. dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
  338. do {
  339. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  340. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  341. {
  342. err = GetLastError();
  343. break;
  344. }
  345. SERVICE_STATUS svcStatus;
  346. if ( !QueryServiceStatus( hService, &svcStatus ))
  347. {
  348. err = ::GetLastError();
  349. break;
  350. }
  351. if ( svcStatus.dwCurrentState == SERVICE_STOPPED )
  352. break; // service already stopped
  353. if (( svcStatus.dwCurrentState == SERVICE_RUNNING ))
  354. {
  355. if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus ))
  356. {
  357. err = GetLastError();
  358. break;
  359. }
  360. for ( dwSleepTotal = 0 ;
  361. dwSleepTotal < dwSvcMaxSleep
  362. && (QueryServiceStatus( hService, & svcStatus ))
  363. && svcStatus.dwCurrentState == SERVICE_STOP_PENDING ;
  364. dwSleepTotal += dwSvcSleepInterval )
  365. {
  366. ::Sleep( dwSvcSleepInterval ) ;
  367. }
  368. }
  369. if ( svcStatus.dwCurrentState != SERVICE_STOPPED )
  370. {
  371. err = dwSleepTotal > dwSvcMaxSleep ?
  372. ERROR_SERVICE_REQUEST_TIMEOUT :
  373. svcStatus.dwWin32ExitCode;
  374. break;
  375. }
  376. } while ( FALSE );
  377. if (hService){CloseServiceHandle(hService);}
  378. if (hScManager){CloseServiceHandle(hScManager);}
  379. iisDebugOut((LOG_TYPE_TRACE, _T("InetStopService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  380. return(err);
  381. }
  382. INT InetDeleteService( LPCTSTR lpServiceName )
  383. {
  384. INT err = 0;
  385. SC_HANDLE hScManager = NULL;
  386. SC_HANDLE hService = NULL;
  387. /*
  388. The DeleteService function marks a service for deletion from the service control manager database.
  389. The database entry is not removed until all open handles to the service have been closed by calls
  390. to the CloseServiceHandle function, and the service is not running. A running service is stopped
  391. by a call to the ControlService function with the SERVICE_CONTROL_STOP control code.
  392. If the service cannot be stopped, the database entry is removed when the system is restarted.
  393. The service control manager deletes the service by deleting the service key and its subkeys from
  394. the registry.
  395. */
  396. // To delete service immediately, we need to stop service first
  397. StopServiceAndDependencies(lpServiceName, FALSE);
  398. do {
  399. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  400. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ||
  401. !::DeleteService( hService ) )
  402. {
  403. err = GetLastError();
  404. break;
  405. }
  406. } while (0);
  407. if (hService){CloseServiceHandle(hService);}
  408. if (hScManager){CloseServiceHandle(hScManager);}
  409. iisDebugOut((LOG_TYPE_TRACE, _T("InetDeleteService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  410. return(err);
  411. }
  412. INT InetCreateDriver(LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType)
  413. {
  414. iisDebugOut_Start1(_T("InetCreateDriver"),(LPTSTR) lpServiceName);
  415. INT err = 0;
  416. SC_HANDLE hScManager = NULL;
  417. SC_HANDLE hService = NULL;
  418. do {
  419. if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL )
  420. {
  421. err = GetLastError();
  422. break;
  423. }
  424. //
  425. // if Driver already exits then just change the parameters
  426. //
  427. if ( CheckifServiceExist( lpServiceName ) == 0 ) {
  428. hService = OpenService( hScManager, lpServiceName, GENERIC_ALL );
  429. if ( hService ) {
  430. if ( ChangeServiceConfig(
  431. hService, // handle to service
  432. SERVICE_KERNEL_DRIVER, // type of service
  433. dwStartType, // when to start service
  434. SERVICE_ERROR_NORMAL, // severity if service fails to start
  435. lpBinaryPathName, // pointer to service binary file name
  436. NULL, // pointer to load ordering group name
  437. NULL, // pointer to variable to get tag identifier
  438. NULL, // pointer to array of dependency names
  439. NULL, // pointer to account name of service
  440. NULL, // pointer to password for service account
  441. lpDisplayName // pointer to display name
  442. ) ){
  443. break;
  444. }
  445. }
  446. } else {
  447. hService = ::CreateService( hScManager, lpServiceName, lpDisplayName,
  448. GENERIC_ALL, SERVICE_KERNEL_DRIVER, dwStartType,
  449. SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL,
  450. NULL, NULL, NULL );
  451. if ( hService ) {
  452. break;
  453. }
  454. }
  455. err = GetLastError();
  456. } while ( FALSE );
  457. if (hService){CloseServiceHandle(hService);}
  458. if (hScManager){CloseServiceHandle(hScManager);}
  459. iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateDriver():Name=%s. Return=0x%x.\n"), lpServiceName, err));
  460. return(err);
  461. }
  462. INT InetCreateService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType, LPCTSTR lpDependencies)
  463. {
  464. iisDebugOut_Start1(_T("InetCreateService"),(LPTSTR) lpServiceName);
  465. INT err = 0;
  466. SC_HANDLE hScManager = NULL;
  467. SC_HANDLE hService = NULL;
  468. do {
  469. if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL )
  470. {
  471. err = GetLastError();
  472. break;
  473. }
  474. hService = ::CreateService( hScManager, lpServiceName, lpDisplayName,
  475. GENERIC_ALL, SERVICE_WIN32_SHARE_PROCESS, dwStartType,
  476. SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL,
  477. lpDependencies, _T("LocalSystem"), NULL );
  478. if ( !hService )
  479. {
  480. err = GetLastError();
  481. break;
  482. }
  483. } while ( FALSE );
  484. if (hService){CloseServiceHandle(hService);}
  485. if (hScManager){CloseServiceHandle(hScManager);}
  486. iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  487. return(err);
  488. }
  489. INT InetConfigService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, LPCTSTR lpDependencies)
  490. {
  491. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService():ServiceName=%s\n"), (LPTSTR) lpServiceName));
  492. INT err = 0;
  493. SC_HANDLE hScManager = NULL;
  494. SC_HANDLE hService = NULL;
  495. do {
  496. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  497. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  498. {
  499. err = GetLastError();
  500. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():OpenSCManager or OpenService: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err));
  501. break;
  502. }
  503. if ( !::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, lpBinaryPathName, NULL, NULL, lpDependencies, _T("LocalSystem"), NULL, lpDisplayName) )
  504. {
  505. err = GetLastError();
  506. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():ChangeServiceConfig: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err));
  507. break;
  508. }
  509. } while ( FALSE );
  510. if (hService) {CloseServiceHandle(hService);}
  511. if (hScManager) {CloseServiceHandle(hScManager);}
  512. iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  513. return(err);
  514. }
  515. INT InetConfigService2( LPCTSTR lpServiceName, LPCTSTR lpDescription)
  516. {
  517. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService2():ServiceName=%s\n"), (LPTSTR) lpServiceName));
  518. INT err = 0;
  519. SC_HANDLE hScManager = NULL;
  520. SC_HANDLE hService = NULL;
  521. SERVICE_DESCRIPTION ServiceDescription;
  522. do {
  523. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  524. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  525. {
  526. err = GetLastError();
  527. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
  528. break;
  529. }
  530. if (lpDescription)
  531. {
  532. if (_tcscmp(lpDescription, _T("")) != 0)
  533. {
  534. ServiceDescription.lpDescription = (LPTSTR) lpDescription;
  535. if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, (LPVOID)&ServiceDescription))
  536. {
  537. err = GetLastError();
  538. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():ChangeServiceConfig2: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
  539. break;
  540. }
  541. }
  542. }
  543. } while ( FALSE );
  544. if (hService) {CloseServiceHandle(hService);}
  545. if (hScManager) {CloseServiceHandle(hScManager);}
  546. iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService2():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  547. return(err);
  548. }
  549. # define SetServiceTypeValues( pSvcTypeValue, dwNS, dwType, dwSize, lpValName, lpVal) \
  550. ( pSvcTypeValue)->dwNameSpace = ( dwNS); \
  551. ( pSvcTypeValue)->dwValueType = ( dwType); \
  552. ( pSvcTypeValue)->dwValueSize = ( dwSize); \
  553. ( pSvcTypeValue)->lpValueName = ( lpValName); \
  554. ( pSvcTypeValue)->lpValue = (PVOID ) ( lpVal); \
  555. # define SetServiceTypeValuesDword( pSvcTypeValue, dwNS, lpValName, lpVal) \
  556. SetServiceTypeValues( (pSvcTypeValue), (dwNS), REG_DWORD, sizeof( DWORD), \
  557. ( lpValName), ( lpVal))
  558. BOOL InetRegisterService( LPCTSTR pszMachine, LPCTSTR pszServiceName, GUID *pGuid, DWORD SapId, DWORD TcpPort, BOOL fAdd )
  559. {
  560. iisDebugOut_Start1(_T("InetRegisterService"),(LPTSTR) pszServiceName);
  561. int err;
  562. WSADATA WsaData;
  563. SERVICE_INFO serviceInfo;
  564. LPSERVICE_TYPE_INFO_ABS lpServiceTypeInfo ;
  565. LPSERVICE_TYPE_VALUE_ABS lpServiceTypeValues ;
  566. BYTE serviceTypeInfoBuffer[sizeof(SERVICE_TYPE_INFO) + 1024];
  567. // Buffer large enough for 3 values ( SERVICE_TYPE_VALUE_ABS)
  568. DWORD Value1 = 1 ;
  569. DWORD SapValue = SapId;
  570. DWORD TcpPortValue = TcpPort;
  571. DWORD statusFlags;
  572. //
  573. // Initialize Windows Sockets DLL
  574. //
  575. err = WSAStartup( 0x0101, & WsaData);
  576. if ( err == SOCKET_ERROR)
  577. {
  578. return ( FALSE);
  579. }
  580. //
  581. // Setup the service information to be passed to SetService() for adding
  582. // or deleting this service. Most of the SERVICE_INFO fields are not
  583. // required for add or delete operation. The main things of interests are
  584. // GUIDs and ServiceSpecificInfo structure.
  585. //
  586. memset( (PVOID ) & serviceInfo, 0, sizeof( serviceInfo)); //null all fields
  587. serviceInfo.lpServiceType = pGuid;
  588. serviceInfo.lpMachineName = (LPTSTR)pszMachine;
  589. //
  590. // The "Blob" will contain the service specific information.
  591. // In this case, fill it with a SERVICE_TYPE_INFO_ABS structure
  592. // and associated information.
  593. //
  594. serviceInfo.ServiceSpecificInfo.pBlobData = serviceTypeInfoBuffer;
  595. serviceInfo.ServiceSpecificInfo.cbSize = sizeof( serviceTypeInfoBuffer);
  596. lpServiceTypeInfo = (LPSERVICE_TYPE_INFO_ABS ) serviceTypeInfoBuffer;
  597. //
  598. // There are totally 3 values associated with this service if we're doing
  599. // both SPX and TCP, there's only one value if TCP.
  600. //
  601. if ( SapId )
  602. {
  603. lpServiceTypeInfo->dwValueCount = 3;
  604. }
  605. else
  606. {
  607. lpServiceTypeInfo->dwValueCount = 1;
  608. }
  609. lpServiceTypeInfo->lpTypeName = (LPTSTR)pszServiceName;
  610. lpServiceTypeValues = lpServiceTypeInfo->Values;
  611. if ( SapId )
  612. {
  613. //
  614. // 1st value: tells the SAP that this is a connection oriented service.
  615. //
  616. SetServiceTypeValuesDword( ( lpServiceTypeValues + 0),
  617. NS_SAP, // Name Space
  618. SERVICE_TYPE_VALUE_CONN, // ValueName
  619. &Value1 // actual value
  620. );
  621. //
  622. // 2nd Value: tells SAP about object type to be used for broadcasting
  623. // the service name.
  624. //
  625. SetServiceTypeValuesDword( ( lpServiceTypeValues + 1),
  626. NS_SAP,
  627. SERVICE_TYPE_VALUE_SAPID,
  628. &SapValue);
  629. //
  630. // 3rd value: tells TCPIP name-space provider about TCP/IP port to be used.
  631. //
  632. SetServiceTypeValuesDword( ( lpServiceTypeValues + 2),
  633. NS_DNS,
  634. SERVICE_TYPE_VALUE_TCPPORT,
  635. &TcpPortValue);
  636. }
  637. else
  638. {
  639. SetServiceTypeValuesDword( ( lpServiceTypeValues + 0),
  640. NS_DNS,
  641. SERVICE_TYPE_VALUE_TCPPORT,
  642. &TcpPortValue);
  643. }
  644. //
  645. // Finally, call SetService to actually perform the operation.
  646. //
  647. err = SetService(
  648. NS_DEFAULT, // all default name spaces
  649. ( fAdd ) ? SERVICE_ADD_TYPE : SERVICE_DELETE_TYPE, // either ADD or DELETE
  650. 0, // dwFlags not used
  651. &serviceInfo, // the service info structure
  652. NULL, // lpServiceAsyncInfo
  653. &statusFlags // additional status information
  654. );
  655. // for some unknown reason, the SERVICE_DELETE_TYPE never remove the related registry
  656. // I have to manually clean it here.
  657. if (!fAdd)
  658. {
  659. CRegKey regSvcTypes(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\ServiceProvider\\ServiceTypes"));
  660. if ((HKEY)regSvcTypes) {regSvcTypes.DeleteTree(pszServiceName);}
  661. }
  662. iisDebugOut((LOG_TYPE_TRACE, _T("InetRegisterService():ServiceName=%s.End.Return=%d.\n"), pszServiceName, err));
  663. return ( err != NO_ERROR);
  664. } // InetRegisterService()
  665. INT CheckifServiceExistAndDependencies( LPCTSTR lpServiceName )
  666. {
  667. INT err = 0;
  668. INT iReturn = 0;
  669. SC_HANDLE hScManager = NULL;
  670. SC_HANDLE hService = NULL;
  671. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  672. BYTE ConfigBuffer[4096];
  673. LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  674. if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  675. {
  676. // Failed, or more likely the service doesn't exist
  677. iReturn = GetLastError();
  678. goto CheckifServiceExistAndDependencies_Exit;
  679. }
  680. // There was no error and the service exists.
  681. // Then let's make sure the actual file exists!!!
  682. // The above calls will only return true if the service has been registered, but
  683. // the call doesn't actually check if the file exists!
  684. // Retrieve the service's config for the BinaryPathName
  685. // if it fails then hey, we don't have a correctly installed service
  686. // so return error!
  687. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  688. {
  689. iReturn = GetLastError();
  690. goto CheckifServiceExistAndDependencies_Exit;
  691. }
  692. if (!ServiceConfig)
  693. {
  694. iReturn = GetLastError();
  695. goto CheckifServiceExistAndDependencies_Exit;
  696. }
  697. if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
  698. {
  699. if (ServiceConfig->lpBinaryPathName)
  700. {
  701. if (IsFileExist(ServiceConfig->lpBinaryPathName))
  702. {
  703. // the service exists and the file exists too!
  704. iReturn = 0;
  705. }
  706. else
  707. {
  708. iReturn = ERROR_FILE_NOT_FOUND;
  709. goto CheckifServiceExistAndDependencies_Exit;
  710. }
  711. }
  712. }
  713. else
  714. {
  715. iReturn = 0;
  716. }
  717. // Get our list of services which we depend upon.
  718. // let's make sure they are registered and exist.
  719. // ServiceConfig->lpDependencies should look something like this
  720. // service\0service\0\0 double null terminated
  721. {
  722. TCHAR * pdest = NULL;
  723. long RightMostNull = 0;
  724. pdest = ServiceConfig->lpDependencies;
  725. do
  726. {
  727. if (*pdest != _T('\0'))
  728. {
  729. RightMostNull = RightMostNull + _tcslen(pdest) + 1;
  730. // Check if the service exists
  731. if (0 != CheckifServiceExistAndDependencies(pdest)){iReturn = err;}
  732. pdest = _tcschr(pdest, _T('\0'));
  733. pdest++;
  734. }
  735. else
  736. {
  737. break;
  738. }
  739. } while (TRUE);
  740. }
  741. CheckifServiceExistAndDependencies_Exit:
  742. if (ServiceConfig) {free(ServiceConfig);}
  743. if (hService) {CloseServiceHandle(hService);}
  744. if (hScManager) {CloseServiceHandle(hScManager);}
  745. return (iReturn);
  746. }
  747. INT CheckifServiceExist( LPCTSTR lpServiceName )
  748. {
  749. INT err = 0;
  750. SC_HANDLE hScManager = NULL;
  751. SC_HANDLE hService = NULL;
  752. if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL
  753. || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  754. {err = GetLastError();}
  755. if (hService) CloseServiceHandle(hService);
  756. if (hScManager) CloseServiceHandle(hScManager);
  757. return (err);
  758. }
  759. /*----------------------------------------------------------------------------------------
  760. Routine Description:
  761. This routine allocates a buffer for the specified service's configuration parameters,
  762. and retrieves those parameters into the buffer. The caller is responsible for freeing
  763. the buffer.
  764. Remarks:
  765. The pointer whose address is contained in ServiceConfig is guaranteed to be NULL upon
  766. return if any error occurred.
  767. -----------------------------------------------------------------------------------------*/
  768. DWORD RetrieveServiceConfig(IN SC_HANDLE ServiceHandle,OUT LPQUERY_SERVICE_CONFIG *ServiceConfig)
  769. {
  770. DWORD ServiceConfigSize = 0, Err;
  771. if (NULL == ServiceConfig)
  772. {
  773. return ERROR_INVALID_PARAMETER;
  774. }
  775. *ServiceConfig = NULL;
  776. while(TRUE)
  777. {
  778. if(QueryServiceConfig(ServiceHandle, *ServiceConfig, ServiceConfigSize, &ServiceConfigSize))
  779. {
  780. //assert(*ServiceConfig);
  781. return NO_ERROR;
  782. }
  783. else
  784. {
  785. Err = GetLastError();
  786. if(*ServiceConfig)
  787. {
  788. free(*ServiceConfig);
  789. *ServiceConfig=NULL;
  790. }
  791. if(Err == ERROR_INSUFFICIENT_BUFFER)
  792. {
  793. // Allocate a larger buffer, and try again.
  794. *ServiceConfig = (LPQUERY_SERVICE_CONFIG) malloc(ServiceConfigSize);
  795. if( !( *ServiceConfig ) )
  796. {
  797. return ERROR_NOT_ENOUGH_MEMORY;
  798. }
  799. }
  800. else
  801. {
  802. *ServiceConfig = NULL;
  803. return Err;
  804. }
  805. }
  806. } // while (TRUE)
  807. }
  808. INT CreateDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency )
  809. {
  810. iisDebugOut_Start1(_T("CreateDependencyForService"),(LPTSTR) lpServiceName);
  811. INT err = 0;
  812. SC_HANDLE hScManager = NULL;
  813. SC_HANDLE hService = NULL;
  814. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  815. TCHAR szTempDependencies[1024];
  816. TCHAR * pszTempDependencies = NULL;
  817. pszTempDependencies = szTempDependencies;
  818. do {
  819. // set up the service first
  820. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  821. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  822. {
  823. err = GetLastError();
  824. break;
  825. }
  826. // Get the existing Service information
  827. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  828. {
  829. err = GetLastError();
  830. break;
  831. }
  832. if(!ServiceConfig)
  833. {
  834. err = GetLastError();
  835. break;
  836. }
  837. // Check if our service is already in there.
  838. // ServiceConfig->lpDependencies should look something like this
  839. // service\0service\0\0 double null terminated
  840. TCHAR * pdest = NULL;
  841. int bFoundFlag = FALSE;
  842. long RightMostNull = 0;
  843. pdest = ServiceConfig->lpDependencies;
  844. do
  845. {
  846. if (*pdest != _T('\0'))
  847. {
  848. RightMostNull = RightMostNull + _tcslen(pdest) + 1;
  849. if (_tcsicmp(pdest, lpDependency) == 0)
  850. {
  851. bFoundFlag = TRUE;
  852. break;
  853. }
  854. // copy the entry onto our string which we'll use later.
  855. _tcscpy(pszTempDependencies,pdest);
  856. // position pointer to the end
  857. pszTempDependencies=pszTempDependencies + RightMostNull;
  858. pdest = _tcschr(pdest, _T('\0'));
  859. pdest++;
  860. }
  861. else
  862. {
  863. break;
  864. }
  865. } while (TRUE);
  866. // if the service is already on the dependency list then exit
  867. if (bFoundFlag == TRUE)
  868. {
  869. break;
  870. }
  871. // The Service is not there So Let's add it to the end of the list then change the data
  872. // The pointer should be at the beginning or at the next entry point
  873. _tcscpy(pszTempDependencies, lpDependency);
  874. // position pointer to the end
  875. pszTempDependencies=pszTempDependencies + (_tcslen(pszTempDependencies) + 1);
  876. // add another null to the end
  877. *pszTempDependencies = _T('\0');
  878. if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL))
  879. {
  880. err = GetLastError();
  881. break;
  882. }
  883. } while ( FALSE );
  884. if (ServiceConfig) {free(ServiceConfig);}
  885. if (hService) {CloseServiceHandle(hService);}
  886. if (hScManager) {CloseServiceHandle(hScManager);}
  887. iisDebugOut((LOG_TYPE_TRACE, _T("CreateDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  888. return err;
  889. }
  890. INT RemoveDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency )
  891. {
  892. iisDebugOut_Start1(_T("RemoveDependencyForService"),(LPTSTR) lpServiceName);
  893. INT err = 0;
  894. SC_HANDLE hScManager = NULL;
  895. SC_HANDLE hService = NULL;
  896. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  897. TCHAR szTempDependencies[1024];
  898. TCHAR * pszTempDependencies = NULL;
  899. pszTempDependencies = szTempDependencies;
  900. do {
  901. // set up the service first
  902. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  903. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  904. {
  905. err = GetLastError();
  906. break;
  907. }
  908. // Get the existing Service information
  909. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  910. {
  911. err = GetLastError();
  912. break;
  913. }
  914. if(!ServiceConfig)
  915. {
  916. err = GetLastError();
  917. break;
  918. }
  919. // Check if our service is already in there.
  920. // ServiceConfig->lpDependencies should look something like this
  921. // service\0service\0\0 double null terminated
  922. TCHAR * pdest = NULL;
  923. int bFoundFlag = FALSE;
  924. long RightMostNull = 0;
  925. _tcsset(szTempDependencies, _T('\0'));
  926. pdest = ServiceConfig->lpDependencies;
  927. do
  928. {
  929. if (*pdest != _T('\0'))
  930. {
  931. RightMostNull = RightMostNull + _tcslen(pdest) + 1;
  932. if (_tcsicmp(pdest, lpDependency) == 0)
  933. {
  934. bFoundFlag = TRUE;
  935. }
  936. else
  937. {
  938. // copy the entry onto our string which we'll use later.
  939. _tcscpy(pszTempDependencies,pdest);
  940. // position pointer to the end
  941. pszTempDependencies=pszTempDependencies + RightMostNull;
  942. *pszTempDependencies = _T('\0');
  943. /*
  944. if (_tcslen(szTempDependencies) == 0)
  945. memcpy(szTempDependencies, pdest, _tcslen(pdest) + 1);
  946. else
  947. memcpy(szTempDependencies + _tcslen(szTempDependencies) + 1, pdest, _tcslen(pdest) + 1);
  948. */
  949. }
  950. pdest = _tcschr(pdest, _T('\0'));
  951. pdest++;
  952. }
  953. else
  954. {
  955. break;
  956. }
  957. } while (TRUE);
  958. // if the service was in the list.
  959. // Then let's remove it.
  960. if (bFoundFlag == FALSE)
  961. {
  962. break;
  963. }
  964. if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL))
  965. {
  966. err = GetLastError();
  967. break;
  968. }
  969. } while ( FALSE );
  970. if (ServiceConfig) {free(ServiceConfig);}
  971. if (hService) {CloseServiceHandle(hService);}
  972. if (hScManager) {CloseServiceHandle(hScManager);}
  973. iisDebugOut((LOG_TYPE_TRACE, _T("RemoveDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  974. return err;
  975. }
  976. INT DisplayDependencyForService( LPCTSTR lpServiceName)
  977. {
  978. INT err = 0;
  979. SC_HANDLE hScManager = NULL;
  980. SC_HANDLE hService = NULL;
  981. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  982. do {
  983. // set up the service first
  984. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  985. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  986. {
  987. err = GetLastError();
  988. break;
  989. }
  990. // Get the existing Service information
  991. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  992. {
  993. err = GetLastError();
  994. break;
  995. }
  996. if(!ServiceConfig)
  997. {
  998. err = GetLastError();
  999. break;
  1000. }
  1001. // Check if our service is already in there.
  1002. // ServiceConfig->lpDependencies should look something like this
  1003. // service\0service\0\0 double null terminated
  1004. TCHAR * pdest = NULL;
  1005. int bFoundFlag = FALSE;
  1006. long RightMostNull = 0;
  1007. pdest = ServiceConfig->lpDependencies;
  1008. do
  1009. {
  1010. if (*pdest != _T('\0'))
  1011. {
  1012. pdest = _tcschr(pdest, _T('\0'));
  1013. pdest++;
  1014. }
  1015. else
  1016. {
  1017. break;
  1018. }
  1019. } while (TRUE);
  1020. } while ( FALSE );
  1021. if (ServiceConfig) {free(ServiceConfig);}
  1022. if (hService) {CloseServiceHandle(hService);}
  1023. if (hScManager) {CloseServiceHandle(hScManager);}
  1024. return err;
  1025. }
  1026. //
  1027. //Routine Description:
  1028. // Stop the named service and all those services which depend upon it.
  1029. // And if the service is hung and can't be stopped, then kill the darn thing.
  1030. //
  1031. //Arguments:
  1032. // ServiceName (Name of service to stop)
  1033. //
  1034. //Return Status:
  1035. // TRUE - Indicates service successfully stopped
  1036. // FALSE - Timeout occurred.
  1037. //
  1038. int StopServiceAndDependencies(LPCTSTR ServiceName, int AddToRestartList)
  1039. {
  1040. iisDebugOut_Start1(_T("StopServiceAndDependencies"),(LPTSTR) ServiceName);
  1041. int Err = 0;
  1042. int iBeforeServiceStatus = 0;
  1043. SC_HANDLE ScManagerHandle = NULL;
  1044. SC_HANDLE ServiceHandle = NULL;
  1045. SERVICE_STATUS ServiceStatus;
  1046. DWORD Timeout;
  1047. int iReturn = FALSE;
  1048. DWORD TimeoutMaxSecs = 60;
  1049. DWORD dwSvcMaxSleep = 0;
  1050. //
  1051. // Open a handle to the Service.
  1052. //
  1053. ScManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT );
  1054. if (ScManagerHandle == NULL)
  1055. {
  1056. Err = GetLastError();
  1057. iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenSCManager: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
  1058. goto Cleanup;
  1059. }
  1060. ServiceHandle = OpenService(ScManagerHandle,ServiceName,SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | SERVICE_QUERY_CONFIG );
  1061. if ( ServiceHandle == NULL )
  1062. {
  1063. Err = GetLastError();
  1064. if (Err == ERROR_SERVICE_DOES_NOT_EXIST)
  1065. {
  1066. iReturn = TRUE;
  1067. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("StopServiceAndDependencies():%s Service does not exist.\n"), ServiceName));
  1068. }
  1069. else
  1070. {
  1071. iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenService: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
  1072. }
  1073. goto Cleanup;
  1074. }
  1075. // Get the before service status.
  1076. if (QueryServiceStatus(ServiceHandle, &ServiceStatus))
  1077. {
  1078. iBeforeServiceStatus = ServiceStatus.dwCurrentState;
  1079. }
  1080. //
  1081. // Ask the service to stop.
  1082. //
  1083. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
  1084. {
  1085. Err = GetLastError();
  1086. // If there are dependent services running,
  1087. // determine their names and stop them.
  1088. if ( Err == ERROR_DEPENDENT_SERVICES_RUNNING )
  1089. {
  1090. BYTE ConfigBuffer[4096];
  1091. LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  1092. DWORD BytesNeeded;
  1093. DWORD ServiceCount;
  1094. DWORD ServiceIndex;
  1095. //
  1096. // Get the names of the dependent services.
  1097. //
  1098. if ( !EnumDependentServices( ServiceHandle,SERVICE_ACTIVE,ServiceConfig,sizeof(ConfigBuffer),&BytesNeeded,&ServiceCount ) )
  1099. {
  1100. Err = GetLastError();
  1101. iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():EnumDependentServices: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
  1102. goto Cleanup;
  1103. }
  1104. //
  1105. // Stop those services.
  1106. //
  1107. for ( ServiceIndex=0; ServiceIndex<ServiceCount; ServiceIndex++ )
  1108. {
  1109. StopServiceAndDependencies( ServiceConfig[ServiceIndex].lpServiceName, AddToRestartList);
  1110. }
  1111. //
  1112. // Ask the original service to stop.
  1113. //
  1114. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
  1115. {
  1116. Err = GetLastError();
  1117. // check if the service is already stopped..
  1118. if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
  1119. {
  1120. // check if the service is alread stopped.
  1121. if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  1122. {
  1123. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  1124. {
  1125. iReturn = TRUE;
  1126. goto Cleanup;
  1127. }
  1128. }
  1129. }
  1130. else
  1131. {
  1132. // The service must be in a hung mode. Let's kill it.
  1133. iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies():'%s' Service must be in a hung mode. Let's kill it.\n"), ServiceName));
  1134. KillService(ServiceHandle);
  1135. goto WaitLoop;
  1136. }
  1137. goto Cleanup;
  1138. }
  1139. }
  1140. else
  1141. {
  1142. // check if the service is already stopped..
  1143. if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
  1144. {
  1145. // check if the service is alread stopped.
  1146. if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  1147. {
  1148. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  1149. {
  1150. Err = ServiceStatus.dwCurrentState;
  1151. iReturn = TRUE;
  1152. goto Cleanup;
  1153. }
  1154. }
  1155. }
  1156. else
  1157. {
  1158. // The service must be in a hung mode. Let's kill it.
  1159. iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies():'%s' Service must be in a hung mode. Let's kill it.\n"), ServiceName));
  1160. KillService(ServiceHandle);
  1161. goto WaitLoop;
  1162. }
  1163. goto Cleanup;
  1164. }
  1165. }
  1166. else
  1167. {
  1168. // We successfully asked the service to stop...
  1169. }
  1170. WaitLoop:
  1171. // Calculcate if this is a "special" service which we
  1172. // need to give more time to in order to stop.
  1173. dwSvcMaxSleep = InetStopExtraWait(ServiceName);
  1174. // dwSvcMaxSleep returns 3 minute intervals. so default dwSvcMaxSleep will be 180000 (3 minutes)
  1175. // we need to convert this into how many seconds
  1176. TimeoutMaxSecs = (dwSvcMaxSleep/1000);
  1177. // Loop waiting for the service to stop.
  1178. for ( Timeout=0; Timeout < TimeoutMaxSecs; Timeout++ )
  1179. {
  1180. // Return or continue waiting depending on the state of the service.
  1181. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED )
  1182. {
  1183. // The service successfully stopped.
  1184. iisDebugOut((LOG_TYPE_TRACE, _T("StopServiceAndDependencies(): %s Service stopped.\n"), ServiceName));
  1185. iReturn = TRUE;
  1186. goto Cleanup;
  1187. }
  1188. // Wait a second for the service to finish stopping.
  1189. Sleep( 1000 );
  1190. // Query the status of the service again.
  1191. if (! QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  1192. {
  1193. Err = GetLastError();
  1194. iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():QueryServiceStatus: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
  1195. goto Cleanup;
  1196. }
  1197. // if the service we are trying to stop is a driver,
  1198. // then heck we should just get out of here..
  1199. if (TRUE == IsThisServiceADriver(ServiceName))
  1200. {
  1201. iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies(): %s service is a driver, and can only be removed upon reboot.\n"), ServiceName));
  1202. goto Cleanup;
  1203. }
  1204. }
  1205. // if we get here then the service failed to stop.
  1206. iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies(): failed to stop %s service.\n"), ServiceName));
  1207. Cleanup:
  1208. if ( ScManagerHandle != NULL ) {(VOID) CloseServiceHandle(ScManagerHandle);}
  1209. if ( ServiceHandle != NULL ) {(VOID) CloseServiceHandle(ServiceHandle);}
  1210. // if we successfully stopped this service, then
  1211. // add it to the restart service list
  1212. if (iReturn == TRUE)
  1213. {
  1214. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("StopServiceAndDependencies(): %s service. success.\n"), ServiceName));
  1215. if (iBeforeServiceStatus == SERVICE_RUNNING)
  1216. {
  1217. if (AddToRestartList) {ServicesRestartList_Add(ServiceName);}
  1218. }
  1219. }
  1220. return iReturn;
  1221. }
  1222. // ----------------------------------------------
  1223. // The service must be in a hung mode. Let's kill it.
  1224. // Get the binary path name and use that to kill it.
  1225. // Return true on successfull kill. false otherwise.
  1226. // ----------------------------------------------
  1227. int KillService(SC_HANDLE ServiceHandle)
  1228. {
  1229. int iReturn = FALSE;
  1230. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  1231. int iFlagPutItBack = FALSE;
  1232. // Retrieve the service's config for the BinaryPathName
  1233. // if failed then just return
  1234. if(RetrieveServiceConfig(ServiceHandle, &ServiceConfig) != NO_ERROR)
  1235. {
  1236. goto KillService_Exit;
  1237. }
  1238. if(!ServiceConfig)
  1239. {
  1240. goto KillService_Exit;
  1241. }
  1242. // The Service can be one of these types:
  1243. // SERVICE_WIN32_OWN_PROCESS: A service type flag that indicates a Win32 service that runs in its own process.
  1244. // SERVICE_WIN32_SHARE_PROCESS: A service type flag that indicates a Win32 service that shares a process with other services.
  1245. // SERVICE_KERNEL_DRIVER: A service type flag that indicates a Windows NT device driver.
  1246. // SERVICE_FILE_SYSTEM_DRIVER: A service type flag that indicates a Windows NT file system driver.
  1247. // SERVICE_INTERACTIVE_PROCESS: A flag that indicates a Win32 service process that can interact with the desktop.
  1248. // Attempt to kill only if it's a process.
  1249. if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
  1250. {
  1251. if ( _tcslen(ServiceConfig->lpBinaryPathName) >= MAX_PATH )
  1252. {
  1253. goto KillService_Exit;
  1254. }
  1255. // parse out the different parts and take only the filename.ext
  1256. TCHAR pfilename_only[ MAX_PATH ];
  1257. TCHAR pextention_only[ MAX_PATH ];
  1258. _tsplitpath( ServiceConfig->lpBinaryPathName, NULL, NULL, pfilename_only, pextention_only);
  1259. if (pextention_only) {_tcscat(pfilename_only,pextention_only);}
  1260. if ( _tcsicmp( pfilename_only, _T("lsass") ) == 0 )
  1261. {
  1262. // No matter what service it is, lets not kill lsass.exe
  1263. goto KillService_Exit;
  1264. }
  1265. // Convert it to ansi for our "kill" function
  1266. char szFile[ MAX_PATH ];
  1267. #if defined(UNICODE) || defined(_UNICODE)
  1268. WideCharToMultiByte( CP_ACP, 0, (WCHAR*)pfilename_only, -1, szFile, MAX_PATH, NULL, NULL );
  1269. #else
  1270. _tcscpy(szFile, pfilename_only);
  1271. #endif
  1272. // Some of these services have some action to do if the service is killed.
  1273. // like IISADMIN has some restart function which will automagically restart the
  1274. // Service if the process is not properly shutdown.
  1275. // We need to disable this deal because We can't have this service just startup by itself again.
  1276. iFlagPutItBack = FALSE;
  1277. if (_tcsicmp(ServiceConfig->lpServiceStartName,_T("IISADMIN")) == 0)
  1278. {
  1279. // Go lookup the registry for "FailureCommands" and save that information.
  1280. // retrieve from registry
  1281. CString csFailureCommand;
  1282. CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN);
  1283. if ( (HKEY)regIISADMINParam )
  1284. {
  1285. regIISADMINParam.m_iDisplayWarnings = FALSE;
  1286. if (ERROR_SUCCESS == regIISADMINParam.QueryValue(_T("FailureCommands"), csFailureCommand))
  1287. {
  1288. // Kool, we got it.
  1289. // Set it to do nothing.
  1290. regIISADMINParam.SetValue(_T("FailureCommands"), _T(""));
  1291. iFlagPutItBack = TRUE;
  1292. }
  1293. }
  1294. // kill the service's process
  1295. if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;}
  1296. if (TRUE == iFlagPutItBack)
  1297. {
  1298. CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN);
  1299. if ( (HKEY)regIISADMINParam )
  1300. {
  1301. regIISADMINParam.SetValue(_T("FailureCommands"), csFailureCommand);
  1302. }
  1303. }
  1304. }
  1305. else
  1306. {
  1307. if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;}
  1308. }
  1309. }
  1310. KillService_Exit:
  1311. if (ServiceConfig) {free(ServiceConfig);}
  1312. return iReturn;
  1313. }
  1314. INT CheckifServiceMarkedForDeletion( LPCTSTR lpServiceName )
  1315. {
  1316. INT iReturn = FALSE;
  1317. INT err = 0;
  1318. SC_HANDLE hScManager = NULL;
  1319. SC_HANDLE hService = NULL;
  1320. // set up the service first
  1321. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  1322. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  1323. {
  1324. err = GetLastError();
  1325. goto CheckifServiceMarkedForDeletion_Exit;
  1326. }
  1327. SERVICE_STATUS svcStatus;
  1328. if ( !QueryServiceStatus( hService, &svcStatus ))
  1329. {
  1330. err = ::GetLastError();
  1331. goto CheckifServiceMarkedForDeletion_Exit;
  1332. }
  1333. if ( svcStatus.dwCurrentState == SERVICE_RUNNING )
  1334. {
  1335. // We will only get this ERROR_SERVICE_MARKED_FOR_DELETE
  1336. // message if the service is already running.
  1337. if ( !::StartService( hService, 0, NULL ))
  1338. {
  1339. err = ::GetLastError();
  1340. if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {iReturn = TRUE;}
  1341. goto CheckifServiceMarkedForDeletion_Exit;
  1342. }
  1343. }
  1344. CheckifServiceMarkedForDeletion_Exit:
  1345. if (hService) CloseServiceHandle(hService);
  1346. if (hScManager) CloseServiceHandle(hScManager);
  1347. return iReturn;
  1348. }
  1349. //
  1350. // warning: This will leave the lpServiceToValidate in the started mode upon exit!
  1351. //
  1352. int ValidateDependentService(LPCTSTR lpServiceToValidate, LPCTSTR lpServiceWhichIsDependent)
  1353. {
  1354. iisDebugOut_Start1(_T("ValidateDependentService"),(LPTSTR) lpServiceToValidate);
  1355. int iReturn = FALSE;
  1356. INT err = 0;
  1357. int iFailFlag = FALSE;
  1358. SC_HANDLE hScManager = NULL;
  1359. SC_HANDLE hService = NULL;
  1360. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  1361. // Let's validate that the lpServiceToValidate is installed fine.
  1362. // Check if the lpServiceToValidate service EVEN exists
  1363. err = CheckifServiceExistAndDependencies(lpServiceToValidate);
  1364. if ( err != 0 )
  1365. {
  1366. MyMessageBox(NULL, IDS_DEPENDENT_UPON_THIS_SVC_ERR, lpServiceWhichIsDependent,lpServiceWhichIsDependent,err, MB_OK | MB_SETFOREGROUND);
  1367. }
  1368. else
  1369. {
  1370. // Try to start the service
  1371. err = InetStartService(lpServiceToValidate);
  1372. if (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING)
  1373. {
  1374. err = NERR_Success;
  1375. iReturn = TRUE;
  1376. goto ValidateDependentService_Exit;
  1377. }
  1378. // Service returned an error when we tried to start it.
  1379. // Check if the error = ERROR_SERVICE_DEPENDENCY_FAIL
  1380. if (err == ERROR_SERVICE_DEPENDENCY_FAIL)
  1381. {
  1382. // Loop thru this services dependencies and try to
  1383. // start them, to find out which one failed to start.
  1384. iFailFlag = FALSE;
  1385. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceToValidate, GENERIC_ALL )) == NULL ) {iFailFlag = TRUE;}
  1386. // Get the existing Service information
  1387. if (iFailFlag != TRUE) {if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) {iFailFlag = TRUE;}}
  1388. if (iFailFlag != TRUE) {if(!ServiceConfig){iFailFlag = TRUE;}}
  1389. // Get the dependencies
  1390. if (iFailFlag != TRUE)
  1391. {
  1392. TCHAR * pdest = NULL;
  1393. long RightMostNull = 0;
  1394. pdest = ServiceConfig->lpDependencies;
  1395. do
  1396. {
  1397. if (*pdest != _T('\0'))
  1398. {
  1399. RightMostNull = RightMostNull + _tcslen(pdest) + 1;
  1400. // Try to start the service...
  1401. err = InetStartService(pdest);
  1402. if (err)
  1403. {
  1404. if (err != ERROR_SERVICE_ALREADY_RUNNING)
  1405. {
  1406. // The pdest
  1407. // Service was unable to start because...
  1408. // MyMessageBox(NULL, IDS_UNABLE_TO_START, pdest, err, MB_OK | MB_SETFOREGROUND);
  1409. iisDebugOut((LOG_TYPE_ERROR, _T("ValidateDependentService():Unable to start ServiceName=%s.\n"), pdest));
  1410. }
  1411. }
  1412. pdest = _tcschr(pdest, _T('\0'));
  1413. pdest++;
  1414. }
  1415. else
  1416. {
  1417. break;
  1418. }
  1419. } while (TRUE);
  1420. }
  1421. }
  1422. else
  1423. {
  1424. MyMessageBox(NULL, IDS_UNABLE_TO_START, lpServiceToValidate, err, MB_OK | MB_SETFOREGROUND);
  1425. }
  1426. }
  1427. ValidateDependentService_Exit:
  1428. if (ServiceConfig) {free(ServiceConfig);}
  1429. if (hService) {CloseServiceHandle(hService);}
  1430. if (hScManager) {CloseServiceHandle(hScManager);}
  1431. iisDebugOut_End1(_T("ValidateDependentService"), lpServiceToValidate, LOG_TYPE_TRACE);
  1432. return iReturn;
  1433. }
  1434. int LogEnumServicesStatus(void)
  1435. {
  1436. int iReturn = FALSE;
  1437. #ifndef _CHICAGO_
  1438. BOOL success = 0;
  1439. SC_HANDLE scm = NULL;
  1440. LPENUM_SERVICE_STATUS status = NULL;
  1441. DWORD numServices=0, sizeNeeded=0, resume=0;
  1442. // Open a connection to the SCM
  1443. //scm = OpenSCManager(0, 0, GENERIC_ALL);
  1444. scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  1445. if (!scm)
  1446. {
  1447. iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():OpenSCManager. FAILED. err=0x%x\n"), GetLastError()));
  1448. goto CallEnumServicesStatus_Exit;
  1449. }
  1450. // get the number of bytes to allocate
  1451. // MAKE SURE resume starts at 0
  1452. resume = 0;
  1453. success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume);
  1454. if (GetLastError() != ERROR_MORE_DATA)
  1455. {
  1456. iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError()));
  1457. goto CallEnumServicesStatus_Exit;
  1458. }
  1459. // Allocate space
  1460. status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded);
  1461. if( status == NULL )
  1462. {
  1463. goto CallEnumServicesStatus_Exit;
  1464. }
  1465. // Get the status records. Making an assumption
  1466. // here that no new services get added during
  1467. // the allocation (could lock the database to
  1468. // guarantee that...)
  1469. resume = 0;
  1470. success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume);
  1471. if (!success)
  1472. {
  1473. iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError()));
  1474. goto CallEnumServicesStatus_Exit;
  1475. }
  1476. DWORD i;
  1477. for (i=0; i < numServices; i++)
  1478. {
  1479. switch(status[i].ServiceStatus.dwCurrentState)
  1480. {
  1481. case SERVICE_STOPPED:
  1482. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOPPED [%s].\n"), status[i].lpServiceName));
  1483. break;
  1484. case SERVICE_START_PENDING:
  1485. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_START_PENDING [%s].\n"), status[i].lpServiceName));
  1486. break;
  1487. case SERVICE_STOP_PENDING:
  1488. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOP_PENDING [%s].\n"), status[i].lpServiceName));
  1489. break;
  1490. case SERVICE_RUNNING:
  1491. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_RUNNING [%s].\n"), status[i].lpServiceName));
  1492. break;
  1493. case SERVICE_CONTINUE_PENDING:
  1494. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_CONTINUE_PENDING [%s].\n"), status[i].lpServiceName));
  1495. break;
  1496. case SERVICE_PAUSE_PENDING:
  1497. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSE_PENDING [%s].\n"), status[i].lpServiceName));
  1498. break;
  1499. case SERVICE_PAUSED:
  1500. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSED [%s].\n"), status[i].lpServiceName));
  1501. break;
  1502. }
  1503. }
  1504. iReturn = TRUE;
  1505. CallEnumServicesStatus_Exit:
  1506. if (status){LocalFree(status);}
  1507. if (scm) {CloseServiceHandle(scm);}
  1508. #endif
  1509. return iReturn;
  1510. }
  1511. int InetIsThisExeAService(LPCTSTR lpFileNameToCheck, LPTSTR lpReturnServiceName)
  1512. {
  1513. int iReturn = FALSE;
  1514. #ifndef _CHICAGO_
  1515. BOOL success = 0;
  1516. SC_HANDLE scm = NULL;
  1517. LPENUM_SERVICE_STATUS status = NULL;
  1518. DWORD numServices=0, sizeNeeded=0, resume=0;
  1519. _tcscpy(lpReturnServiceName, _T(""));
  1520. // Open a connection to the SCM
  1521. //scm = OpenSCManager(0, 0, GENERIC_ALL);
  1522. scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  1523. if (!scm)
  1524. {
  1525. iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():OpenSCManager. FAILED. err=0x%x\n"), GetLastError()));
  1526. goto InetIsThisExeAService_Exit;
  1527. }
  1528. // get the number of bytes to allocate
  1529. // MAKE SURE resume starts at 0
  1530. resume = 0;
  1531. success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume);
  1532. if (GetLastError() != ERROR_MORE_DATA)
  1533. {
  1534. iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError()));
  1535. goto InetIsThisExeAService_Exit;
  1536. }
  1537. // Allocate space
  1538. status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded);
  1539. if( status == NULL )
  1540. {
  1541. goto InetIsThisExeAService_Exit;
  1542. }
  1543. // Get the status records. Making an assumption
  1544. // here that no new services get added during
  1545. // the allocation (could lock the database to
  1546. // guarantee that...)
  1547. resume = 0;
  1548. success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume);
  1549. if (!success)
  1550. {
  1551. iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError()));
  1552. goto InetIsThisExeAService_Exit;
  1553. }
  1554. DWORD i;
  1555. for (i=0; i < numServices; i++)
  1556. {
  1557. // Use the status[i].lpServiceName
  1558. // to query the service and find out it's binary filename
  1559. if (TRUE == InetIsThisExeAService_Worker(status[i].lpServiceName, lpFileNameToCheck))
  1560. {
  1561. iReturn = TRUE;
  1562. // copy in the service name into the return string.
  1563. _tcscpy(lpReturnServiceName, status[i].lpServiceName);
  1564. goto InetIsThisExeAService_Exit;
  1565. }
  1566. }
  1567. InetIsThisExeAService_Exit:
  1568. if (status){LocalFree(status);}
  1569. if (scm) {CloseServiceHandle(scm);}
  1570. #endif
  1571. return iReturn;
  1572. }
  1573. int InetIsThisExeAService_Worker(LPCTSTR lpServiceName, LPCTSTR lpFileNameToCheck)
  1574. {
  1575. int iReturn = FALSE;
  1576. INT err = 0;
  1577. SC_HANDLE hScManager = NULL;
  1578. SC_HANDLE hService = NULL;
  1579. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  1580. BYTE ConfigBuffer[4096];
  1581. LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  1582. if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  1583. {
  1584. // Failed, or more likely the service doesn't exist
  1585. //iReturn = GetLastError();
  1586. goto InetIsThisExeAService_Worker_Exit;
  1587. }
  1588. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  1589. {
  1590. //iReturn = GetLastError();
  1591. goto InetIsThisExeAService_Worker_Exit;
  1592. }
  1593. if(!ServiceConfig)
  1594. {
  1595. goto InetIsThisExeAService_Worker_Exit;
  1596. }
  1597. if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
  1598. {
  1599. if (ServiceConfig->lpBinaryPathName)
  1600. {
  1601. if (_tcsicmp(lpFileNameToCheck, ServiceConfig->lpBinaryPathName) == 0)
  1602. {
  1603. //We found a match!!!!!
  1604. iReturn = TRUE;
  1605. }
  1606. else
  1607. {
  1608. // we did not find a match, based on c:\path\filename and c:\path\filename
  1609. // maybe we try "filename.exe" and "filename.exe"????
  1610. TCHAR szBinaryNameOnly[_MAX_FNAME];
  1611. TCHAR szFileNameToCheckNameOnly[_MAX_FNAME];
  1612. if (TRUE == ReturnFileNameOnly((LPCTSTR) ServiceConfig->lpBinaryPathName, szBinaryNameOnly))
  1613. {
  1614. if (TRUE == ReturnFileNameOnly((LPCTSTR) lpFileNameToCheck, szFileNameToCheckNameOnly))
  1615. {
  1616. if (_tcsicmp(szFileNameToCheckNameOnly, szBinaryNameOnly) == 0)
  1617. {
  1618. //We found a match!!!!!
  1619. iReturn = TRUE;
  1620. }
  1621. }
  1622. }
  1623. }
  1624. }
  1625. }
  1626. InetIsThisExeAService_Worker_Exit:
  1627. if (ServiceConfig) {free(ServiceConfig);}
  1628. if (hService) {CloseServiceHandle(hService);}
  1629. if (hScManager) {CloseServiceHandle(hScManager);}
  1630. return iReturn;
  1631. }
  1632. int IsThisServiceADriver(LPCTSTR lpServiceName)
  1633. {
  1634. int iReturn = FALSE;
  1635. SC_HANDLE hScManager = NULL;
  1636. SC_HANDLE hService = NULL;
  1637. LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
  1638. BYTE ConfigBuffer[4096];
  1639. LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  1640. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  1641. {
  1642. // Failed, or more likely the service doesn't exist
  1643. //iReturn = GetLastError();
  1644. goto IsThisServiceADriver_Exit;
  1645. }
  1646. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  1647. {
  1648. //iReturn = GetLastError();
  1649. goto IsThisServiceADriver_Exit;
  1650. }
  1651. if(!ServiceConfig)
  1652. {
  1653. //iReturn = GetLastError();
  1654. goto IsThisServiceADriver_Exit;
  1655. }
  1656. if ( (ServiceConfig->dwServiceType & SERVICE_KERNEL_DRIVER) || (ServiceConfig->dwServiceType & SERVICE_FILE_SYSTEM_DRIVER))
  1657. {
  1658. iReturn = TRUE;
  1659. }
  1660. IsThisServiceADriver_Exit:
  1661. if (ServiceConfig) {free(ServiceConfig);}
  1662. if (hService) {CloseServiceHandle(hService);}
  1663. if (hScManager) {CloseServiceHandle(hScManager);}
  1664. return iReturn;
  1665. }
  1666. int CreateDriver(CString csDriverName, CString csDisplayName, CString csFileName)
  1667. {
  1668. DWORD dwReturn = ERROR_SUCCESS;
  1669. CString csBinPath;
  1670. CString csFile;
  1671. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CreateDriver:%s:%s start.\n"), csDriverName, csFileName));
  1672. csBinPath = _T("\\SystemRoot\\System32\\drivers\\");
  1673. csBinPath += csFileName;
  1674. // Check if the file even exists first.
  1675. csFile = g_pTheApp->m_csSysDir;
  1676. csFile += _T("\\Drivers\\");
  1677. csFile += csFileName;
  1678. if (!IsFileExist(csFile))
  1679. {
  1680. dwReturn = ERROR_FILE_NOT_FOUND;
  1681. goto CreateDriver_Exit;
  1682. }
  1683. //
  1684. // Attempt to create the service, could fail if this is an
  1685. // Refresh Install will leave the driver from the prior
  1686. // Install, becuse if we delete in the remove phase it will
  1687. // get marked for deletion and not get readded now.
  1688. // this could happen in a upgrade as well....
  1689. //
  1690. dwReturn = InetCreateDriver(csDriverName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, SERVICE_DEMAND_START);
  1691. if ( dwReturn != ERROR_SUCCESS )
  1692. {
  1693. if (dwReturn == ERROR_SERVICE_EXISTS)
  1694. {
  1695. iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Service exists.\n"), csDriverName));
  1696. dwReturn = ERROR_SUCCESS;
  1697. }
  1698. else
  1699. {
  1700. iisDebugOut((LOG_TYPE_ERROR, _T("CreateDriver:%s:failed to create service Err=0x%x.\n"), csDriverName, dwReturn));
  1701. MyMessageBox(NULL, IDS_UNABLE_TO_CREATE_DRIVER, csDriverName, dwReturn, MB_OK | MB_SETFOREGROUND);
  1702. }
  1703. }
  1704. else
  1705. {
  1706. iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Successfully created.\n"), csDriverName));
  1707. }
  1708. CreateDriver_Exit:
  1709. return dwReturn;
  1710. }
  1711. DWORD CreateDriver_Wrap(CString csDriverName, CString csDisplayName, CString csFileName,BOOL bDisplayMsgOnErrFlag)
  1712. {
  1713. int bFinishedFlag = FALSE;
  1714. UINT iMsg = NULL;
  1715. DWORD dwReturn = ERROR_SUCCESS;
  1716. // Create or Config driver spud.sys, NT Server product onloy!!!
  1717. if (g_pTheApp->m_eOS != OS_W95)
  1718. {
  1719. do
  1720. {
  1721. dwReturn = CreateDriver(csDriverName, csDisplayName, csFileName);
  1722. if (dwReturn == ERROR_SUCCESS)
  1723. {
  1724. break;
  1725. }
  1726. else
  1727. {
  1728. if (bDisplayMsgOnErrFlag == TRUE)
  1729. {
  1730. iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  1731. switch ( iMsg )
  1732. {
  1733. case IDIGNORE:
  1734. dwReturn = ERROR_SUCCESS;
  1735. goto CreateDriver_Wrap_Exit;
  1736. case IDABORT:
  1737. dwReturn = ERROR_OPERATION_ABORTED;
  1738. goto CreateDriver_Wrap_Exit;
  1739. case IDRETRY:
  1740. break;
  1741. default:
  1742. break;
  1743. }
  1744. }
  1745. else
  1746. {
  1747. // return whatever err happened
  1748. goto CreateDriver_Wrap_Exit;
  1749. }
  1750. }
  1751. } while (dwReturn != ERROR_SUCCESS);
  1752. }
  1753. CreateDriver_Wrap_Exit:
  1754. return dwReturn;
  1755. }
  1756. INT InetConfigServiceInteractive(LPCTSTR lpServiceName, int AddInteractive)
  1757. {
  1758. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigServiceInteractive(%i):ServiceName=%s\n"),AddInteractive,(LPTSTR) lpServiceName));
  1759. INT err = 0;
  1760. SC_HANDLE hScManager = NULL;
  1761. SC_HANDLE hService = NULL;
  1762. LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
  1763. DWORD dwNewServiceType = 0;
  1764. BOOL bDoStuff = FALSE;
  1765. do {
  1766. if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  1767. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  1768. {
  1769. err = GetLastError();
  1770. // if error = ERROR_SERVICE_DOES_NOT_EXIST
  1771. if (ERROR_SERVICE_DOES_NOT_EXIST != err)
  1772. {
  1773. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName,err));
  1774. }
  1775. break;
  1776. }
  1777. if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
  1778. {
  1779. err = GetLastError();
  1780. break;
  1781. }
  1782. if(!ServiceConfig)
  1783. {
  1784. err = GetLastError();
  1785. break;
  1786. }
  1787. // Interactive flag can only work on own_process or share_process types
  1788. if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
  1789. {
  1790. // default it incase someone changes code below and logic gets messed up
  1791. dwNewServiceType = ServiceConfig->dwServiceType;
  1792. // if the interactive flag is already there
  1793. // then don't do jack, otherwise, add it on
  1794. if (ServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS)
  1795. {
  1796. // only do stuff if we're asked to remove it!
  1797. if (FALSE == AddInteractive)
  1798. {
  1799. // Remove it from the mask!
  1800. dwNewServiceType = ServiceConfig->dwServiceType & (~SERVICE_INTERACTIVE_PROCESS);
  1801. bDoStuff = TRUE;
  1802. }
  1803. }
  1804. else
  1805. {
  1806. if (TRUE == AddInteractive)
  1807. {
  1808. dwNewServiceType = ServiceConfig->dwServiceType | SERVICE_INTERACTIVE_PROCESS;
  1809. bDoStuff = TRUE;
  1810. }
  1811. }
  1812. if (TRUE == bDoStuff)
  1813. {
  1814. if ( !::ChangeServiceConfig(hService, dwNewServiceType, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL) )
  1815. {
  1816. err = GetLastError();
  1817. iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():ChangeServiceConfig: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
  1818. break;
  1819. }
  1820. }
  1821. else
  1822. {
  1823. break;
  1824. }
  1825. }
  1826. else
  1827. {
  1828. break;
  1829. }
  1830. } while ( FALSE );
  1831. if (ServiceConfig) {free(ServiceConfig);}
  1832. if (hService) {CloseServiceHandle(hService);}
  1833. if (hScManager) {CloseServiceHandle(hScManager);}
  1834. iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigServiceInteractive():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
  1835. return(err);
  1836. }
  1837. // This function trys to create the www service
  1838. int MyCreateService(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription)
  1839. {
  1840. int iReturn = !ERROR_SUCCESS;
  1841. int err = NERR_Success;
  1842. TSTR strDependencies2( MAX_PATH );
  1843. iisDebugOut((LOG_TYPE_TRACE, _T("MyCreateService:%s,%s,%s,%s.\n"),csServiceName, csDisplayName, csBinPath, csDependencies));
  1844. if ( !strDependencies2.Copy( csDependencies.GetBuffer(0) ) ||
  1845. !strDependencies2.Append( _T(":") )
  1846. )
  1847. {
  1848. return iReturn;
  1849. }
  1850. // make sure it ends with a ":"
  1851. // and then replace all the ":", with a "\0" null....
  1852. TCHAR *p = (LPTSTR) strDependencies2.QueryStr();
  1853. while (*p)
  1854. {
  1855. // change ":" to a null "\0"
  1856. if (*p == _T(':')){*p = _T('\0');}
  1857. p = _tcsinc(p);
  1858. }
  1859. err = InetCreateService(csServiceName,
  1860. (LPCTSTR)csDisplayName,
  1861. (LPCTSTR)csBinPath,
  1862. SERVICE_AUTO_START,
  1863. strDependencies2.QueryStr());
  1864. if ( err != NERR_Success )
  1865. {
  1866. // check if the error is because the service already exists...
  1867. if (err == ERROR_SERVICE_EXISTS)
  1868. {
  1869. // Since the service should exist by the time we get here,
  1870. // let's make sure it has the dependency we want it to have.
  1871. err = InetConfigService(csServiceName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, strDependencies2.QueryStr());
  1872. if (err != NERR_Success)
  1873. {
  1874. SetLastError(err);
  1875. goto MyCreateService_Exit;
  1876. }
  1877. }
  1878. else
  1879. {
  1880. SetLastError(err);
  1881. goto MyCreateService_Exit;
  1882. }
  1883. }
  1884. // Use newer api to add the description field.
  1885. err = InetConfigService2(csServiceName, (LPCTSTR)csDescription);
  1886. if (err != NERR_Success)
  1887. {
  1888. SetLastError(err);
  1889. goto MyCreateService_Exit;
  1890. }
  1891. // there was no error in the InetCreateService call.
  1892. // so everything is hunky dory
  1893. iReturn = ERROR_SUCCESS;
  1894. MyCreateService_Exit:
  1895. return iReturn;
  1896. }
  1897. DWORD CreateService_wrap(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription, BOOL bDisplayMsgOnErrFlag)
  1898. {
  1899. int bFinishedFlag = FALSE;
  1900. UINT iMsg = NULL;
  1901. DWORD dwReturn = ERROR_SUCCESS;
  1902. do
  1903. {
  1904. dwReturn = MyCreateService(csServiceName, csDisplayName, csBinPath, csDependencies, csDescription);
  1905. if (dwReturn == ERROR_SUCCESS)
  1906. {
  1907. break;
  1908. }
  1909. else
  1910. {
  1911. if (bDisplayMsgOnErrFlag == TRUE)
  1912. {
  1913. iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  1914. switch ( iMsg )
  1915. {
  1916. case IDIGNORE:
  1917. dwReturn = ERROR_SUCCESS;
  1918. goto CreateService_wrap_Exit;
  1919. case IDABORT:
  1920. dwReturn = ERROR_OPERATION_ABORTED;
  1921. goto CreateService_wrap_Exit;
  1922. case IDRETRY:
  1923. break;
  1924. default:
  1925. break;
  1926. }
  1927. }
  1928. else
  1929. {
  1930. // return whatever err happened
  1931. goto CreateService_wrap_Exit;
  1932. }
  1933. }
  1934. } while (dwReturn != ERROR_SUCCESS);
  1935. CreateService_wrap_Exit:
  1936. return dwReturn;
  1937. }
  1938. // function: ChangeServiceDepenedency
  1939. //
  1940. // Change the dependency of a particular service, to either add or remove another service name
  1941. // from it
  1942. //
  1943. // ex. ChangeServiceDependency( W3SSL, TRUE, IISADMIN ) - Would make W3SSL dependant on IISADMIN
  1944. //
  1945. // Parameters:
  1946. // szServiceName - The service to modify
  1947. // bAddDependency - Add or remove dependency
  1948. // szDependantService - The service that you wand to add as the depenedency
  1949. //
  1950. BOOL
  1951. ChangeServiceDependency(LPTSTR szServiceName, BOOL bAddDependency, LPTSTR szDependantService)
  1952. {
  1953. SC_HANDLE hService;
  1954. SC_HANDLE hSCManager;
  1955. BOOL bRet = FALSE;
  1956. BOOL bChange = FALSE;
  1957. BUFFER buffConfig;
  1958. DWORD dwSizeRequired;
  1959. TSTR_MSZ mszDependencies;
  1960. hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
  1961. if ( hSCManager == NULL )
  1962. {
  1963. return FALSE;
  1964. }
  1965. hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG );
  1966. if ( hService == NULL )
  1967. {
  1968. CloseServiceHandle( hSCManager );
  1969. return FALSE;
  1970. }
  1971. if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) &&
  1972. ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
  1973. buffConfig.Resize( dwSizeRequired ) &&
  1974. QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired )
  1975. )
  1976. {
  1977. // We have successfully retrieved the service info, so lets modify it
  1978. if ( mszDependencies.Copy( ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->lpDependencies ) )
  1979. {
  1980. if ( bAddDependency )
  1981. {
  1982. if ( !mszDependencies.IsPresent(szDependantService, FALSE) )
  1983. {
  1984. bRet = mszDependencies.Add( szDependantService );
  1985. bChange = TRUE;
  1986. }
  1987. else
  1988. {
  1989. // It is already present, so we don't need to add again
  1990. bRet = TRUE;
  1991. }
  1992. }
  1993. else
  1994. {
  1995. if ( mszDependencies.IsPresent(szDependantService, FALSE) )
  1996. {
  1997. bRet = mszDependencies.Remove( szDependantService, FALSE );
  1998. bChange = TRUE;
  1999. }
  2000. else
  2001. {
  2002. // Since it is not there, lets not worry about it
  2003. bRet = TRUE;
  2004. }
  2005. }
  2006. if ( bRet && bChange )
  2007. {
  2008. bRet = ChangeServiceConfig( hService, // Service Handle
  2009. SERVICE_NO_CHANGE, // Service Type
  2010. SERVICE_NO_CHANGE, // Startup Type
  2011. SERVICE_NO_CHANGE, // Error Control
  2012. NULL, // Binary Path
  2013. NULL, // Load Order Group
  2014. NULL, // TagID
  2015. mszDependencies.QueryMultiSz(), // Dependencies
  2016. NULL, // Service Start Name
  2017. NULL, // Password
  2018. NULL ); // Display Name
  2019. }
  2020. }
  2021. }
  2022. CloseServiceHandle( hSCManager );
  2023. CloseServiceHandle( hService );
  2024. return bRet;
  2025. }