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.

1097 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name :
  4. iisadmin.cxx
  5. Abstract:
  6. Contains the admin functions of the IIS_SERVICE class
  7. Author:
  8. Johnson Apacible (JohnsonA) 24-June-1996
  9. --*/
  10. #include "tcpdllp.hxx"
  11. #include <rpc.h>
  12. #include <tsunami.hxx>
  13. #include <iistypes.hxx>
  14. #include "inetreg.h"
  15. #include "tcpcons.h"
  16. #include "apiutil.h"
  17. BOOL
  18. PopulateSiteArray(
  19. LPINET_INFO_SITE_LIST * ppSites,
  20. PVOID pvUnused,
  21. IN IIS_SERVER_INSTANCE * pInst
  22. );
  23. PIIS_SERVICE
  24. IIS_SERVICE::FindFromServiceInfoList(
  25. IN DWORD dwServiceId
  26. )
  27. /*++
  28. Description:
  29. Finds a given Services Info object from the global list.
  30. Arguments:
  31. dwServiceId - Service id of service to look for.
  32. Returns:
  33. pointer to service object, if found.
  34. NULL, otherwise.
  35. --*/
  36. {
  37. PLIST_ENTRY listEntry;
  38. PIIS_SERVICE pInetSvc;
  39. //
  40. // Loop through the list of running internet servers and call the callback
  41. // for each server that has one of the service id bits set
  42. //
  43. AcquireGlobalLock( );
  44. for ( listEntry = sm_ServiceInfoListHead.Flink;
  45. listEntry != &sm_ServiceInfoListHead;
  46. listEntry = listEntry->Flink ) {
  47. pInetSvc = CONTAINING_RECORD(
  48. listEntry,
  49. IIS_SERVICE,
  50. m_ServiceListEntry );
  51. if ( dwServiceId == pInetSvc->QueryServiceId() &&
  52. (pInetSvc->QueryCurrentServiceState() == SERVICE_RUNNING ||
  53. pInetSvc->QueryCurrentServiceState() == SERVICE_PAUSED ) ) {
  54. //
  55. // reference and return
  56. //
  57. if ( !pInetSvc->CheckAndReference( ) ) {
  58. IF_DEBUG( INSTANCE ) {
  59. DBGPRINTF((DBG_CONTEXT,
  60. "Failed to reference service %d\n", dwServiceId));
  61. }
  62. pInetSvc = NULL;
  63. }
  64. ReleaseGlobalLock( );
  65. return pInetSvc;
  66. }
  67. }
  68. ReleaseGlobalLock( );
  69. IF_DEBUG( INSTANCE ) {
  70. DBGPRINTF((DBG_CONTEXT,
  71. "FindFromServiceList cannot find service %d\n", dwServiceId));
  72. }
  73. return NULL;
  74. } // IIS_SERVICE::FindFromServiceInfoList
  75. BOOL
  76. IIS_SERVICE::SetServiceAdminInfo(
  77. IN DWORD dwLevel,
  78. IN DWORD dwServiceId,
  79. IN DWORD dwInstance,
  80. IN BOOL fCommonConfig,
  81. IN INETA_CONFIG_INFO * pConfigInfo
  82. )
  83. /*++
  84. Description:
  85. Sets the service configuration.
  86. Arguments:
  87. dwLevel - Info level
  88. dwServiceId - ID of service to set
  89. dwInstance - ID of instance to set
  90. fCommonConfig - Determines if we should set the common or the service
  91. configuration
  92. pConfigInfo - Configuration structure
  93. Returns:
  94. TRUE on sucess and FALSE if there is a failure
  95. --*/
  96. {
  97. BOOL fRet = TRUE;
  98. PIIS_SERVICE pInetSvc;
  99. DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
  100. IF_DEBUG( INSTANCE ) {
  101. DBGPRINTF((DBG_CONTEXT,
  102. "SetServiceAdmin called for svc %d inst %d\n",
  103. dwServiceId, dwInstance));
  104. }
  105. pInetSvc = FindFromServiceInfoList( dwServiceId );
  106. if ( pInetSvc == NULL ) {
  107. SetLastError( ERROR_SERVICE_NOT_ACTIVE);
  108. fRet = FALSE;
  109. goto exit;
  110. }
  111. //
  112. // Set the parameters and update
  113. //
  114. fRet = pInetSvc->SetInstanceConfiguration(
  115. dwInstance,
  116. dwLevel,
  117. fCommonConfig,
  118. pConfigInfo );
  119. //
  120. // This was referenced in Find
  121. //
  122. pInetSvc->Dereference( );
  123. exit:
  124. return fRet;
  125. } // IIS_SERVICE::SetServiceAdminInfo
  126. BOOL
  127. IIS_SERVICE::GetServiceAdminInfo(
  128. IN DWORD dwLevel,
  129. IN DWORD dwServiceId,
  130. IN DWORD dwInstance,
  131. IN BOOL fCommonConfig,
  132. OUT PDWORD nRead,
  133. OUT LPINETA_CONFIG_INFO * ppConfigInfo
  134. )
  135. /*++
  136. Description:
  137. Gets the service configuration.
  138. Arguments:
  139. dwLevel - Info level of this operation
  140. dwServiceId - ID of service to get
  141. dwInstance - ID of instance to get
  142. fCommonConfig - Determines if we should get the common or the service
  143. configuration
  144. pBuffer - on return, will contains a pointer to
  145. the configuration block
  146. Returns:
  147. TRUE on sucess and FALSE if there is a failure
  148. --*/
  149. {
  150. BOOL fRet = FALSE;
  151. PIIS_SERVICE pInetSvc;
  152. DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
  153. IF_DEBUG( INSTANCE ) {
  154. DBGPRINTF((DBG_CONTEXT,
  155. "GetServiceAdmin called for svc %d inst %x\n",
  156. dwServiceId, dwInstance));
  157. }
  158. pInetSvc = FindFromServiceInfoList( dwServiceId );
  159. if ( pInetSvc == NULL ) {
  160. SetLastError( ERROR_SERVICE_NOT_ACTIVE);
  161. goto exit;
  162. }
  163. //
  164. // Get the params
  165. //
  166. fRet = pInetSvc->GetInstanceConfiguration(
  167. dwInstance,
  168. dwLevel,
  169. fCommonConfig,
  170. nRead,
  171. ppConfigInfo
  172. );
  173. //
  174. // This was referenced in Find
  175. //
  176. pInetSvc->Dereference( );
  177. exit:
  178. return fRet;
  179. } // IIS_SERVICE::GetServiceAdminInfo
  180. BOOL
  181. IIS_SERVICE::GetServiceSiteInfo(
  182. IN DWORD dwServiceId,
  183. OUT LPINET_INFO_SITE_LIST * ppSites
  184. )
  185. /*++
  186. Description:
  187. Gets the list of service instances.
  188. Arguments:
  189. dwServiceId - ID of service to get
  190. ppSites - on return, will contain a pointer to
  191. the array of sites
  192. Returns:
  193. TRUE on sucess and FALSE if there is a failure
  194. --*/
  195. {
  196. BOOL fRet = FALSE;
  197. PIIS_SERVICE pInetSvc;
  198. DWORD cInstances = 0;
  199. LPINET_INFO_SITE_LIST pSites;
  200. DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
  201. IF_DEBUG( INSTANCE ) {
  202. DBGPRINTF((DBG_CONTEXT,
  203. "GetServiceSiteInfo called for svc %d\n",
  204. dwServiceId));
  205. }
  206. pInetSvc = FindFromServiceInfoList( dwServiceId );
  207. if ( pInetSvc == NULL ) {
  208. SetLastError( ERROR_SERVICE_NOT_ACTIVE);
  209. return FALSE;
  210. }
  211. //
  212. // Get the params
  213. //
  214. pInetSvc->AcquireServiceLock(TRUE);
  215. cInstances = pInetSvc->QueryInstanceCount();
  216. //allocate enough memory to hold the Site Info Arrary
  217. pSites = (LPINET_INFO_SITE_LIST)
  218. midl_user_allocate (sizeof(INET_INFO_SITE_LIST) + sizeof(INET_INFO_SITE_ENTRY)*cInstances);
  219. if (!pSites) {
  220. pInetSvc->ReleaseServiceLock(TRUE);
  221. //This was referenced in Find
  222. pInetSvc->Dereference( );
  223. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  224. return FALSE;
  225. }
  226. *ppSites = pSites;
  227. pSites->cEntries = 0;
  228. fRet = pInetSvc->EnumServiceInstances(
  229. (PVOID) ppSites,
  230. NULL,
  231. (PFN_INSTANCE_ENUM) PopulateSiteArray
  232. );
  233. if (!fRet) {
  234. for (DWORD i=0; i<pSites->cEntries; i++) {
  235. midl_user_free(pSites->aSiteEntry[i].pszComment);
  236. }
  237. midl_user_free(pSites);
  238. *ppSites = NULL;
  239. }
  240. pInetSvc->ReleaseServiceLock(TRUE);
  241. //This was referenced in Find
  242. pInetSvc->Dereference( );
  243. return fRet;
  244. } // IIS_SERVICE::GetServiceSiteInfo
  245. BOOL
  246. PopulateSiteArray(
  247. LPINET_INFO_SITE_LIST * ppSites,
  248. PVOID pvUnused,
  249. IN IIS_SERVER_INSTANCE * pInst
  250. )
  251. /*++
  252. Description:
  253. Fills the ppSites array with the instance id and site comment.
  254. Arguments:
  255. pvUnused - not used
  256. pInst - pointer to service instance
  257. ppSites - on return, will contain a pointer to
  258. the array of sites
  259. Returns:
  260. TRUE on sucess and FALSE if there is a failure
  261. --*/
  262. {
  263. DWORD cbComment = 0;
  264. LPINET_INFO_SITE_LIST pSites = *ppSites;
  265. //Set the instance ID
  266. pSites->aSiteEntry[pSites->cEntries].dwInstance = pInst->QueryInstanceId();
  267. //allocate memory for the site name
  268. cbComment = (strlen(pInst->QuerySiteName())+1) * sizeof(WCHAR);
  269. pSites->aSiteEntry[pSites->cEntries].pszComment = (LPWSTR)midl_user_allocate(cbComment);
  270. if (!(pSites->aSiteEntry[pSites->cEntries].pszComment))
  271. {
  272. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  273. return FALSE;
  274. }
  275. //
  276. // Need unicode conversion here
  277. //
  278. if (!MultiByteToWideChar( CP_ACP, // code page
  279. MB_PRECOMPOSED, // character-type options
  280. pInst->QuerySiteName(), // address of string to map
  281. -1, // number of bytes in string
  282. pSites->aSiteEntry[pSites->cEntries].pszComment, // address of wide-character buffer
  283. cbComment / sizeof(WCHAR) // size of buffer
  284. ))
  285. {
  286. pSites->aSiteEntry[pSites->cEntries].pszComment[0] = L'\0';
  287. }
  288. pSites->cEntries++;
  289. return TRUE;
  290. } //PopulateSiteArray
  291. DWORD
  292. IIS_SERVICE::GetNewInstanceId(
  293. VOID
  294. )
  295. /*++
  296. Description:
  297. Returns a new instance ID.
  298. Arguments:
  299. None.
  300. Returns:
  301. A non zero dword containing the instance ID.
  302. 0 if there was an error.
  303. --*/
  304. {
  305. DWORD dwId;
  306. CHAR regParamKey[MAX_PATH+1];
  307. MB mb( (IMDCOM*) QueryMDObject() );
  308. AcquireServiceLock( );
  309. for (; ; ) {
  310. dwId = ++m_maxInstanceId;
  311. if ( m_maxInstanceId > INET_INSTANCE_MAX ) {
  312. m_maxInstanceId = INET_INSTANCE_MIN;
  313. }
  314. //
  315. // Make sure the metapath does not exist
  316. //
  317. GetMDInstancePath( dwId, regParamKey );
  318. if ( !mb.Open( regParamKey ) ) {
  319. DBG_ASSERT(GetLastError() == ERROR_FILE_NOT_FOUND);
  320. if ( GetLastError() != ERROR_FILE_NOT_FOUND ) {
  321. DBGPRINTF((DBG_CONTEXT,
  322. "Error %d trying to open %s.\n", GetLastError(), regParamKey ));
  323. dwId = 0;
  324. }
  325. break;
  326. }
  327. }
  328. ReleaseServiceLock( );
  329. IF_DEBUG( INSTANCE ) {
  330. DBGPRINTF((DBG_CONTEXT, "GetNewInstanceId returns %d\n", dwId));
  331. }
  332. return dwId;
  333. } // IIS_SERVICE::GetNewInstanceId
  334. BOOL
  335. IIS_SERVICE::SetInstanceConfiguration(
  336. IN DWORD dwInstance,
  337. IN DWORD dwLevel,
  338. IN BOOL fCommonConfig,
  339. IN LPINETA_CONFIG_INFO pConfig
  340. )
  341. /*++
  342. Description:
  343. Set the configuration for the instance.
  344. Arguments:
  345. dwInstance - Instance number to find - IGNORED FOR SET!!
  346. dwLevel - level of information to set
  347. pCommonConfig - Whether info is common or service specific
  348. pConfig - pointer to the configuration block
  349. Returns:
  350. A dword containing the instance ID.
  351. --*/
  352. {
  353. BOOL fRet = FALSE;
  354. PLIST_ENTRY listEntry;
  355. PIIS_SERVER_INSTANCE pInstance;
  356. IF_DEBUG( INSTANCE ) {
  357. DBGPRINTF((DBG_CONTEXT,
  358. "SetInstanceConfiguration called for instance %d\n", dwInstance));
  359. }
  360. //
  361. // Try to find this instance
  362. //
  363. AcquireServiceLock( TRUE );
  364. //
  365. // Find the instance in the instance list
  366. //
  367. if ( dwInstance == INET_INSTANCE_ROOT ) {
  368. DBG_ASSERT( !"Explicit default instance no longer supported inherited from metabase)\n" );
  369. pInstance = NULL;
  370. } else {
  371. pInstance = FindIISInstance( QueryDownLevelInstance() );
  372. }
  373. if ( pInstance != NULL ) {
  374. goto found;
  375. }
  376. SetLastError(ERROR_FILE_NOT_FOUND);
  377. DBG_ASSERT(!fRet);
  378. goto exit;
  379. found:
  380. if ( fCommonConfig ) {
  381. fRet = pInstance->SetCommonConfig( pConfig, TRUE);
  382. } else {
  383. fRet = pInstance->SetServiceConfig( (CHAR *) pConfig);
  384. }
  385. exit:
  386. ReleaseServiceLock( TRUE );
  387. return fRet;
  388. } // IIS_SERVICE::SetInstanceConfiguration
  389. BOOL
  390. IIS_SERVICE::GetInstanceConfiguration(
  391. IN DWORD dwInstance,
  392. IN DWORD dwLevel,
  393. IN BOOL fCommonConfig,
  394. OUT PDWORD nRead,
  395. OUT LPINETA_CONFIG_INFO * pBuffer
  396. )
  397. /*++
  398. Description:
  399. Get the configuration for the instance.
  400. Arguments:
  401. dwInstance - Instance number to find - IGNORED!!
  402. dwLevel - level of information to get
  403. pCommonConfig - Whether info is common or service specific
  404. nRead - pointer to a DWORD where the number of entries to be
  405. returned is set.
  406. pBuffer - pointer to the configuration block
  407. Returns:
  408. A dword containing the instance ID.
  409. --*/
  410. {
  411. PLIST_ENTRY listEntry;
  412. PIIS_SERVER_INSTANCE pInstance;
  413. DWORD nInstances = 1;
  414. DWORD nSize;
  415. PCHAR pConfig;
  416. //
  417. // Set and Get only work against the default instance
  418. //
  419. dwInstance = QueryDownLevelInstance();
  420. IF_DEBUG( INSTANCE ) {
  421. DBGPRINTF((DBG_CONTEXT,
  422. "GetInstanceConfiguration [%x][%d] called for instance %x L%d\n",
  423. this, fCommonConfig, dwInstance, dwLevel));
  424. }
  425. //
  426. // We support only 1
  427. //
  428. *nRead = 0;
  429. *pBuffer = NULL;
  430. if ( fCommonConfig ) {
  431. DBG_ASSERT( dwLevel == 1 );
  432. nSize = sizeof( INETA_CONFIG_INFO );
  433. } else {
  434. DWORD err;
  435. nSize = GetServiceConfigInfoSize(dwLevel);
  436. if ( nSize == 0 ) {
  437. SetLastError(ERROR_INVALID_LEVEL);
  438. return(FALSE);
  439. }
  440. }
  441. //
  442. // Try to find this instance
  443. //
  444. AcquireServiceLock( );
  445. if ( dwInstance == INET_INSTANCE_ALL ) {
  446. nInstances = QueryInstanceCount( );
  447. if ( nInstances == 0 ) {
  448. goto exit;
  449. }
  450. IF_DEBUG(INSTANCE) {
  451. DBGPRINTF((DBG_CONTEXT,"%d instances found\n",nInstances));
  452. }
  453. }
  454. *pBuffer = (LPINETA_CONFIG_INFO) MIDL_user_allocate(nInstances * nSize);
  455. if ( *pBuffer == NULL ) {
  456. goto error_exit;
  457. }
  458. ZeroMemory( *pBuffer, nInstances * nSize );
  459. //
  460. // Loop through the list of running internet servers and call the callback
  461. // for each server that has one of the service id bits set
  462. //
  463. pConfig = (CHAR *) *pBuffer;
  464. if ( dwInstance != INET_INSTANCE_ROOT ) {
  465. for ( listEntry = m_InstanceListHead.Flink;
  466. listEntry != &m_InstanceListHead;
  467. listEntry = listEntry->Flink ) {
  468. pInstance = CONTAINING_RECORD(
  469. listEntry,
  470. IIS_SERVER_INSTANCE,
  471. m_InstanceListEntry );
  472. if ( (dwInstance == pInstance->QueryInstanceId()) ||
  473. (dwInstance == INET_INSTANCE_ALL) ||
  474. (dwInstance == INET_INSTANCE_FIRST) ) {
  475. if ( fCommonConfig ) {
  476. if ( !pInstance->GetCommonConfig(pConfig,dwLevel) ) {
  477. goto error_exit;
  478. }
  479. } else {
  480. if ( !pInstance->GetServiceConfig(pConfig,dwLevel) ) {
  481. goto error_exit;
  482. }
  483. }
  484. //
  485. // if not get all, return.
  486. //
  487. (*nRead)++;
  488. pConfig += nSize;
  489. if ( dwInstance != INET_INSTANCE_ALL ) {
  490. break;
  491. }
  492. }
  493. }
  494. } else {
  495. DBG_ASSERT( !"Default instance no longer supported!\n" );
  496. }
  497. exit:
  498. if ( *nRead == 0 ) {
  499. if ( dwInstance != INET_INSTANCE_ALL ) {
  500. SetLastError(ERROR_FILE_NOT_FOUND);
  501. goto error_exit;
  502. }
  503. }
  504. ReleaseServiceLock( );
  505. DBG_ASSERT(nInstances == *nRead);
  506. return TRUE;
  507. error_exit:
  508. ReleaseServiceLock( );
  509. IF_DEBUG(ERROR) {
  510. DBGPRINTF((DBG_CONTEXT,"Error %x in GetInstanceConfiguration\n",
  511. GetLastError()));
  512. }
  513. if ( *pBuffer != NULL ) {
  514. MIDL_user_free(*pBuffer);
  515. *pBuffer = NULL;
  516. }
  517. *nRead = 0;
  518. return(FALSE);
  519. } // IIS_SERVICE::GetInstanceConfiguration
  520. PIIS_SERVER_INSTANCE
  521. IIS_SERVICE::FindIISInstance(
  522. IN DWORD dwInstance
  523. )
  524. /*++
  525. Description:
  526. Find the instance
  527. *** Service lock assumed held ***
  528. Arguments:
  529. dwInstance - Instance number to find
  530. Returns:
  531. Pointer to the instance.
  532. NULL if not found.
  533. --*/
  534. {
  535. BOOL fRet = TRUE;
  536. PLIST_ENTRY listEntry;
  537. PIIS_SERVER_INSTANCE pInstance;
  538. //
  539. // Find the instance in the instance list
  540. //
  541. for ( listEntry = m_InstanceListHead.Flink;
  542. listEntry != &m_InstanceListHead;
  543. listEntry = listEntry->Flink ) {
  544. pInstance = CONTAINING_RECORD(
  545. listEntry,
  546. IIS_SERVER_INSTANCE,
  547. m_InstanceListEntry );
  548. if ( (dwInstance == pInstance->QueryInstanceId()) ||
  549. (dwInstance == INET_INSTANCE_FIRST) ) {
  550. return pInstance;
  551. }
  552. }
  553. IF_DEBUG( INSTANCE ) {
  554. DBGPRINTF((DBG_CONTEXT,
  555. "FindIISInstance: Cannot find instance %d\n", dwInstance));
  556. }
  557. SetLastError(ERROR_FILE_NOT_FOUND);
  558. return(NULL);
  559. } // IIS_SERVICE::FindIISInstance
  560. BOOL
  561. IIS_SERVICE::DeleteInstanceInfo(
  562. IN DWORD dwInstance
  563. )
  564. {
  565. PIIS_SERVER_INSTANCE pInstance;
  566. DWORD err = NO_ERROR;
  567. IF_DEBUG( INSTANCE ) {
  568. DBGPRINTF((DBG_CONTEXT,
  569. "DeleteInstanceInfo called for %d\n", dwInstance));
  570. }
  571. //
  572. // Find the instance and close it
  573. //
  574. AcquireServiceLock( TRUE );
  575. //
  576. // Find the instance in the instance list
  577. //
  578. pInstance = FindIISInstance( dwInstance );
  579. if( pInstance == NULL ) {
  580. err = ERROR_FILE_NOT_FOUND;
  581. } else {
  582. //
  583. // Remove it from the list
  584. //
  585. RemoveEntryList( &pInstance->m_InstanceListEntry );
  586. m_nInstance--;
  587. //
  588. // Shut it down
  589. //
  590. pInstance->CloseInstance();
  591. //
  592. // Dereference it
  593. //
  594. pInstance->Dereference( );
  595. }
  596. ReleaseServiceLock( TRUE );
  597. if( err == NO_ERROR ) {
  598. return TRUE;
  599. }
  600. SetLastError( err );
  601. return FALSE;
  602. } // IIS_SERVICE::DeleteInstanceInfo
  603. BOOL
  604. IIS_SERVICE::EnumerateInstanceUsers(
  605. IN DWORD dwInstance,
  606. OUT PDWORD nRead,
  607. OUT PCHAR* pBuffer
  608. )
  609. {
  610. PIIS_SERVER_INSTANCE pInstance;
  611. BOOL fRet;
  612. IF_DEBUG( INSTANCE ) {
  613. DBGPRINTF((DBG_CONTEXT,
  614. "EnumerateInstanceUsers called for service %x (Instance %d)\n",
  615. this, dwInstance ));
  616. }
  617. //
  618. // Find the instance
  619. //
  620. AcquireServiceLock( );
  621. //
  622. // Find the instance in the instance list
  623. //
  624. pInstance = FindIISInstance( dwInstance );
  625. if ( pInstance != NULL ) {
  626. goto found;
  627. }
  628. ReleaseServiceLock( );
  629. SetLastError(ERROR_FILE_NOT_FOUND);
  630. return(FALSE);
  631. found:
  632. fRet = pInstance->EnumerateUsers( pBuffer, nRead );
  633. ReleaseServiceLock( );
  634. return(fRet);
  635. } // IIS_SERVICE::EnumerateInstanceUsers
  636. BOOL
  637. IIS_SERVICE::DisconnectInstanceUser(
  638. IN DWORD dwInstance,
  639. IN DWORD dwIdUser
  640. )
  641. {
  642. PIIS_SERVER_INSTANCE pInstance;
  643. BOOL fRet;
  644. IF_DEBUG( INSTANCE ) {
  645. DBGPRINTF((DBG_CONTEXT,
  646. "DisconnectInstanceUsers called for service %x (Instance %d)\n",
  647. this, dwInstance ));
  648. }
  649. //
  650. // Find the instance
  651. //
  652. AcquireServiceLock( );
  653. //
  654. // Find the instance in the instance list
  655. //
  656. pInstance = FindIISInstance( dwInstance );
  657. if ( pInstance != NULL ) {
  658. goto found;
  659. }
  660. ReleaseServiceLock( );
  661. SetLastError(ERROR_FILE_NOT_FOUND);
  662. return(FALSE);
  663. found:
  664. fRet = pInstance->DisconnectUser( dwIdUser );
  665. ReleaseServiceLock( );
  666. return(fRet);
  667. } // IIS_SERVICE::DisconnectInstanceUsers
  668. BOOL
  669. IIS_SERVICE::GetInstanceStatistics(
  670. IN DWORD dwInstance,
  671. IN DWORD dwLevel,
  672. OUT PCHAR* pBuffer
  673. )
  674. {
  675. PIIS_SERVER_INSTANCE pInstance;
  676. BOOL fRet;
  677. IF_DEBUG( INSTANCE ) {
  678. DBGPRINTF((DBG_CONTEXT,
  679. "GetInstanceStats called for service %x (Instance %d)\n",
  680. this, dwInstance ));
  681. }
  682. //
  683. // Find the instance and close it
  684. //
  685. AcquireServiceLock( TRUE);
  686. if (dwInstance == 0 )
  687. {
  688. fRet = GetGlobalStatistics(dwLevel,pBuffer);
  689. }
  690. else if ( dwInstance == INET_INSTANCE_GLOBAL)
  691. {
  692. //
  693. // We need to aggregate statistics across all instances
  694. //
  695. PLIST_ENTRY listEntry;
  696. PCHAR pStats;
  697. BOOL fFirst = TRUE;
  698. fRet = FALSE;
  699. *pBuffer = NULL;
  700. //
  701. // Loop through all the instances and add their counters
  702. //
  703. for ( listEntry = m_InstanceListHead.Flink;
  704. listEntry != &m_InstanceListHead;
  705. listEntry = listEntry->Flink)
  706. {
  707. pInstance = CONTAINING_RECORD(
  708. listEntry,
  709. IIS_SERVER_INSTANCE,
  710. m_InstanceListEntry );
  711. pInstance->LockThisForRead();
  712. fRet = pInstance->GetStatistics(dwLevel, &pStats);
  713. pInstance->UnlockThis();
  714. if (fRet)
  715. {
  716. if (fFirst)
  717. {
  718. //
  719. // This is the first successful retrieval.
  720. //
  721. *pBuffer = pStats;
  722. fFirst = FALSE;
  723. }
  724. else
  725. {
  726. AggregateStatistics(*pBuffer, pStats);
  727. MIDL_user_free(pStats);
  728. }
  729. }
  730. }
  731. }
  732. else
  733. {
  734. //
  735. // Find the instance in the instance list
  736. //
  737. pInstance = FindIISInstance( dwInstance );
  738. if ( pInstance != NULL )
  739. {
  740. fRet = pInstance->GetStatistics(dwLevel,pBuffer);
  741. }
  742. else
  743. {
  744. SetLastError(ERROR_FILE_NOT_FOUND);
  745. fRet = FALSE;
  746. }
  747. }
  748. ReleaseServiceLock( TRUE);
  749. return(fRet);
  750. } // IIS_SERVICE::GetInstanceStatistics
  751. BOOL
  752. IIS_SERVICE::GetGlobalStatistics(
  753. IN DWORD dwLevel,
  754. OUT PCHAR *pBuffer
  755. )
  756. {
  757. return FALSE;
  758. } // IIS_SERVICE::GetGlobalStatistics
  759. BOOL
  760. IIS_SERVICE::ClearInstanceStatistics(
  761. IN DWORD dwInstance
  762. )
  763. {
  764. PIIS_SERVER_INSTANCE pInstance;
  765. BOOL fRet;
  766. IF_DEBUG( INSTANCE ) {
  767. DBGPRINTF((DBG_CONTEXT,
  768. "ClearInstanceStats called for service %x (instance %d)\n",
  769. this, dwInstance ));
  770. }
  771. //
  772. // Find the instance and close it
  773. //
  774. AcquireServiceLock( );
  775. //
  776. // Find the instance in the instance list
  777. //
  778. pInstance = FindIISInstance( dwInstance );
  779. if ( pInstance != NULL ) {
  780. goto found;
  781. }
  782. ReleaseServiceLock( );
  783. SetLastError(ERROR_FILE_NOT_FOUND);
  784. return(FALSE);
  785. found:
  786. fRet = pInstance->ClearStatistics( );
  787. ReleaseServiceLock( );
  788. return(fRet);
  789. } // IIS_SERVICE::ClearInstanceStatistics
  790.