Source code of Windows XP (NT5)
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.

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