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

812 lines
17 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: csrv.cxx
  7. //
  8. // Contents: Contains methods for CIISServer object
  9. //
  10. // History: 21-1-98 SophiaC Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "iisext.hxx"
  14. #pragma hdrstop
  15. //
  16. // Period to sleep while waiting for service to attain desired state
  17. //
  18. #define SLEEP_INTERVAL (500L)
  19. #define MAX_SLEEP_INST (60000) // For an instance
  20. // Class CIISServer
  21. DEFINE_IPrivateDispatch_Implementation(CIISServer)
  22. DEFINE_DELEGATING_IDispatch_Implementation(CIISServer)
  23. DEFINE_CONTAINED_IADs_Implementation(CIISServer)
  24. DEFINE_IADsExtension_Implementation(CIISServer)
  25. CIISServer::CIISServer():
  26. _pUnkOuter(NULL),
  27. _pADs(NULL),
  28. _pszServerName(NULL),
  29. _pszMetaBasePath(NULL),
  30. _pAdminBase(NULL),
  31. _pDispMgr(NULL),
  32. _fDispInitialized(FALSE)
  33. {
  34. ENLIST_TRACKING(CIISServer);
  35. }
  36. HRESULT
  37. CIISServer::CreateServer(
  38. IUnknown *pUnkOuter,
  39. REFIID riid,
  40. void **ppvObj
  41. )
  42. {
  43. CCredentials Credentials;
  44. CIISServer FAR * pServer = NULL;
  45. HRESULT hr = S_OK;
  46. BSTR bstrAdsPath = NULL;
  47. OBJECTINFO ObjectInfo;
  48. POBJECTINFO pObjectInfo = &ObjectInfo;
  49. CLexer * pLexer = NULL;
  50. LPWSTR pszIISPathName = NULL;
  51. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  52. hr = AllocateServerObject(pUnkOuter, Credentials, &pServer);
  53. BAIL_ON_FAILURE(hr);
  54. //
  55. // get ServerName and pszPath
  56. //
  57. hr = pServer->_pADs->get_ADsPath(&bstrAdsPath);
  58. BAIL_ON_FAILURE(hr);
  59. pLexer = new CLexer();
  60. hr = pLexer->Initialize(bstrAdsPath);
  61. BAIL_ON_FAILURE(hr);
  62. //
  63. // Parse the pathname
  64. //
  65. hr = ADsObject(pLexer, pObjectInfo);
  66. BAIL_ON_FAILURE(hr);
  67. pszIISPathName = AllocADsStr(bstrAdsPath);
  68. if (!pszIISPathName) {
  69. hr = E_OUTOFMEMORY;
  70. BAIL_ON_FAILURE(hr);
  71. }
  72. *pszIISPathName = L'\0';
  73. hr = BuildIISPathFromADsPath(
  74. pObjectInfo,
  75. pszIISPathName
  76. );
  77. BAIL_ON_FAILURE(hr);
  78. hr = pServer->InitializeServerObject(
  79. pObjectInfo->TreeName,
  80. pszIISPathName );
  81. BAIL_ON_FAILURE(hr);
  82. //
  83. // pass non-delegating IUnknown back to the aggregator
  84. //
  85. *ppvObj = (INonDelegatingUnknown FAR *) pServer;
  86. if (bstrAdsPath)
  87. {
  88. ADsFreeString(bstrAdsPath);
  89. }
  90. if (pLexer) {
  91. delete pLexer;
  92. }
  93. if (pszIISPathName ) {
  94. FreeADsStr( pszIISPathName );
  95. }
  96. FreeObjectInfo( &ObjectInfo );
  97. RRETURN(hr);
  98. error:
  99. if (bstrAdsPath)
  100. {
  101. ADsFreeString(bstrAdsPath);
  102. }
  103. if (pLexer) {
  104. delete pLexer;
  105. }
  106. if (pszIISPathName ) {
  107. FreeADsStr( pszIISPathName );
  108. }
  109. FreeObjectInfo( &ObjectInfo );
  110. *ppvObj = NULL;
  111. delete pServer;
  112. RRETURN(hr);
  113. }
  114. CIISServer::~CIISServer( )
  115. {
  116. if (_pszServerName) {
  117. FreeADsStr(_pszServerName);
  118. }
  119. if (_pszMetaBasePath) {
  120. FreeADsStr(_pszMetaBasePath);
  121. }
  122. delete _pDispMgr;
  123. }
  124. STDMETHODIMP
  125. CIISServer::QueryInterface(
  126. REFIID iid,
  127. LPVOID FAR* ppv
  128. )
  129. {
  130. HRESULT hr = S_OK;
  131. hr = _pUnkOuter->QueryInterface(iid,ppv);
  132. RRETURN(hr);
  133. }
  134. HRESULT
  135. CIISServer::AllocateServerObject(
  136. IUnknown *pUnkOuter,
  137. CCredentials& Credentials,
  138. CIISServer ** ppServer
  139. )
  140. {
  141. CIISServer FAR * pServer = NULL;
  142. IADs FAR * pADs = NULL;
  143. CAggregateeDispMgr FAR * pDispMgr = NULL;
  144. HRESULT hr = S_OK;
  145. pServer = new CIISServer();
  146. if (pServer == NULL) {
  147. hr = E_OUTOFMEMORY;
  148. }
  149. BAIL_ON_FAILURE(hr);
  150. pDispMgr = new CAggregateeDispMgr;
  151. if (pDispMgr == NULL) {
  152. hr = E_OUTOFMEMORY;
  153. }
  154. BAIL_ON_FAILURE(hr);
  155. hr = pDispMgr->LoadTypeInfoEntry(
  156. LIBID_ADs,
  157. IID_IADsServiceOperations,
  158. (IADsServiceOperations *)pServer,
  159. DISPID_REGULAR
  160. );
  161. BAIL_ON_FAILURE(hr);
  162. //
  163. // Store the IADs Pointer, but again do NOT ref-count
  164. // this pointer - we keep the pointer around, but do
  165. // a release immediately.
  166. //
  167. hr = pUnkOuter->QueryInterface(IID_IADs, (void **)&pADs);
  168. pADs->Release();
  169. pServer->_pADs = pADs;
  170. //
  171. // Store the pointer to the pUnkOuter object
  172. // AND DO NOT add ref this pointer
  173. //
  174. pServer->_pUnkOuter = pUnkOuter;
  175. //
  176. // Store the pointer to the internal generic object
  177. // AND add ref this pointer
  178. //
  179. pServer->_Credentials = Credentials;
  180. pServer->_pDispMgr = pDispMgr;
  181. *ppServer = pServer;
  182. RRETURN(hr);
  183. error:
  184. delete pDispMgr;
  185. delete pServer;
  186. RRETURN(hr);
  187. }
  188. HRESULT
  189. CIISServer::InitializeServerObject(
  190. LPWSTR pszServerName,
  191. LPWSTR pszPath
  192. )
  193. {
  194. HRESULT hr = S_OK;
  195. if (pszServerName) {
  196. _pszServerName = AllocADsStr(pszServerName);
  197. if (!_pszServerName) {
  198. hr = E_OUTOFMEMORY;
  199. BAIL_ON_FAILURE(hr);
  200. }
  201. }
  202. if (pszPath) {
  203. _pszMetaBasePath = AllocADsStr(pszPath);
  204. if (!_pszMetaBasePath) {
  205. hr = E_OUTOFMEMORY;
  206. BAIL_ON_FAILURE(hr);
  207. }
  208. }
  209. hr = InitServerInfo(pszServerName, &_pAdminBase);
  210. BAIL_ON_FAILURE(hr);
  211. error:
  212. RRETURN(hr);
  213. }
  214. STDMETHODIMP
  215. CIISServer::SetPassword(THIS_ BSTR bstrNewPassword)
  216. {
  217. RRETURN(E_NOTIMPL);
  218. }
  219. //+---------------------------------------------------------------------------
  220. //
  221. // Function: CIISServer::Start
  222. //
  223. // Synopsis: Attempts to start the service specified in _bstrServiceName on
  224. // the server named in _bstrPath.
  225. //
  226. // Arguments:
  227. //
  228. // Returns: HRESULT.
  229. //
  230. // Modifies:
  231. //
  232. // History: 01/04/97 SophiaC Created
  233. //
  234. // Notes:
  235. //----------------------------------------------------------------------------
  236. STDMETHODIMP
  237. CIISServer::Start(THIS)
  238. {
  239. RRETURN(IISControlServer(MD_SERVER_COMMAND_START));
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Function: CIISServer::Stop
  244. //
  245. // Synopsis: Attempts to stop the service specified in _bstrServiceName on
  246. // the server named in _bstrPath.
  247. //
  248. // Arguments:
  249. //
  250. // Returns: HRESULT.
  251. //
  252. // Modifies:
  253. //
  254. // History: 01/04/96 SophiaC Created
  255. //
  256. //----------------------------------------------------------------------------
  257. STDMETHODIMP
  258. CIISServer::Stop(THIS)
  259. {
  260. RRETURN(IISControlServer(MD_SERVER_COMMAND_STOP));
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: CIISServer::Pause
  265. //
  266. // Synopsis: Attempts to pause the service named _bstrServiceName on the
  267. // server named in _bstrPath.
  268. //
  269. // Arguments:
  270. //
  271. // Returns: HRESULT.
  272. //
  273. // Modifies:
  274. //
  275. // History: 01-04-96 SophiaC Created
  276. //
  277. //----------------------------------------------------------------------------
  278. STDMETHODIMP
  279. CIISServer::Pause(THIS)
  280. {
  281. RRETURN(IISControlServer(MD_SERVER_COMMAND_PAUSE));
  282. }
  283. //+---------------------------------------------------------------------------
  284. //
  285. // Function: CIISServer::Continue
  286. //
  287. // Synopsis: Attempts to "unpause" the service specified in _bstrServiceName
  288. // on the server named in _bstrPath.
  289. //
  290. // Arguments:
  291. //
  292. // Returns: HRESULT.
  293. //
  294. // Modifies:
  295. //
  296. // History: 01/04/96 SophiaC Created
  297. //
  298. //----------------------------------------------------------------------------
  299. STDMETHODIMP
  300. CIISServer::Continue(THIS)
  301. {
  302. RRETURN(IISControlServer(MD_SERVER_COMMAND_CONTINUE));
  303. }
  304. STDMETHODIMP
  305. CIISServer::get_Status(THIS_ long FAR* plStatusCode)
  306. {
  307. HRESULT hr = S_OK;
  308. DWORD dwStatus = 0;
  309. DWORD dwCurrentState = 0;
  310. if(plStatusCode == NULL){
  311. RRETURN(E_POINTER);
  312. }
  313. hr = IISGetServerState(METADATA_MASTER_ROOT_HANDLE, &dwCurrentState);
  314. BAIL_ON_FAILURE(hr);
  315. *plStatusCode = (long) dwCurrentState;
  316. error:
  317. RRETURN(hr);
  318. }
  319. //
  320. // Helper Functions
  321. //
  322. HRESULT
  323. CIISServer::IISGetServerState(
  324. METADATA_HANDLE hObjHandle,
  325. PDWORD pdwState
  326. )
  327. {
  328. HRESULT hr = S_OK;
  329. DWORD dwBufferSize = sizeof(DWORD);
  330. METADATA_RECORD mdrMDData;
  331. LPBYTE pBuffer = (LPBYTE)pdwState;
  332. MD_SET_DATA_RECORD(&mdrMDData,
  333. MD_SERVER_STATE, // server state
  334. METADATA_NO_ATTRIBUTES,
  335. IIS_MD_UT_SERVER,
  336. DWORD_METADATA,
  337. dwBufferSize,
  338. pBuffer);
  339. hr = _pAdminBase->GetData(
  340. hObjHandle,
  341. _pszMetaBasePath,
  342. &mdrMDData,
  343. &dwBufferSize
  344. );
  345. if (FAILED(hr)) {
  346. if( hr == MD_ERROR_DATA_NOT_FOUND )
  347. {
  348. //
  349. // If the data is not there, but the path exists, then the
  350. // most likely cause is that the service is not running and
  351. // this object was just created.
  352. //
  353. // Since MD_SERVER_STATE would be set as stopped if the
  354. // service were running when the key is added, we'll just
  355. // say that it's stopped.
  356. //
  357. // Note: starting the server or service will automatically set
  358. // the MB value.
  359. //
  360. *pdwState = MD_SERVER_STATE_STOPPED;
  361. hr = S_FALSE;
  362. }
  363. else if ((HRESULT_CODE(hr) == RPC_S_SERVER_UNAVAILABLE) ||
  364. ((HRESULT_CODE(hr) >= RPC_S_NO_CALL_ACTIVE) &&
  365. (HRESULT_CODE(hr) <= RPC_S_CALL_FAILED_DNE)) ||
  366. hr == RPC_E_DISCONNECTED || hr == MD_ERROR_SECURE_CHANNEL_FAILURE) {
  367. hr = ReCacheAdminBase(_pszServerName, &_pAdminBase);
  368. BAIL_ON_FAILURE(hr);
  369. hr = _pAdminBase->GetData(
  370. hObjHandle,
  371. _pszMetaBasePath,
  372. &mdrMDData,
  373. &dwBufferSize
  374. );
  375. if (FAILED(hr)) {
  376. if( hr == MD_ERROR_DATA_NOT_FOUND )
  377. {
  378. *pdwState = MD_SERVER_STATE_STOPPED;
  379. hr = S_FALSE;
  380. }
  381. }
  382. BAIL_ON_FAILURE(hr);
  383. }
  384. else
  385. {
  386. BAIL_ON_FAILURE(hr);
  387. }
  388. }
  389. error:
  390. RRETURN(hr);
  391. }
  392. //
  393. // Helper routine for ExecMethod.
  394. // Gets Win32 error from the metabase
  395. //
  396. HRESULT
  397. CIISServer::IISGetServerWin32Error(
  398. METADATA_HANDLE hObjHandle,
  399. HRESULT* phrError)
  400. {
  401. DBG_ASSERT(phrError != NULL);
  402. long lWin32Error = 0;
  403. DWORD dwLen;
  404. METADATA_RECORD mr = {
  405. MD_WIN32_ERROR,
  406. METADATA_NO_ATTRIBUTES,
  407. IIS_MD_UT_SERVER,
  408. DWORD_METADATA,
  409. sizeof(DWORD),
  410. (unsigned char*)&lWin32Error,
  411. 0
  412. };
  413. HRESULT hr = _pAdminBase->GetData(
  414. hObjHandle,
  415. _pszMetaBasePath,
  416. &mr,
  417. &dwLen);
  418. if(hr == MD_ERROR_DATA_NOT_FOUND)
  419. {
  420. hr = S_FALSE;
  421. }
  422. //
  423. // Set out param
  424. //
  425. *phrError = HRESULT_FROM_WIN32(lWin32Error);
  426. RRETURN(hr);
  427. }
  428. //
  429. // Helper routine for ExecMethod.
  430. // Clears Win32 error
  431. //
  432. HRESULT
  433. CIISServer::IISClearServerWin32Error(
  434. METADATA_HANDLE hObjHandle )
  435. {
  436. long lWin32Error = 0;
  437. METADATA_RECORD mr = {
  438. MD_WIN32_ERROR,
  439. METADATA_VOLATILE,
  440. IIS_MD_UT_SERVER,
  441. DWORD_METADATA,
  442. sizeof(DWORD),
  443. (unsigned char*)&lWin32Error,
  444. 0
  445. };
  446. HRESULT hr = _pAdminBase->SetData(
  447. hObjHandle,
  448. L"",
  449. &mr );
  450. RRETURN(hr);
  451. }
  452. HRESULT
  453. CIISServer::IISControlServer(
  454. DWORD dwControl
  455. )
  456. {
  457. METADATA_HANDLE hObjHandle = NULL;
  458. DWORD dwTargetState;
  459. DWORD dwPendingState;
  460. DWORD dwState = 0;
  461. DWORD dwSleepTotal = 0L;
  462. HRESULT hr = S_OK;
  463. HRESULT hrMbNode = S_OK;
  464. switch(dwControl)
  465. {
  466. case MD_SERVER_COMMAND_STOP:
  467. dwTargetState = MD_SERVER_STATE_STOPPED;
  468. dwPendingState = MD_SERVER_STATE_STOPPING;
  469. break;
  470. case MD_SERVER_COMMAND_START:
  471. dwTargetState = MD_SERVER_STATE_STARTED;
  472. dwPendingState = MD_SERVER_STATE_STARTING;
  473. break;
  474. case MD_SERVER_COMMAND_CONTINUE:
  475. dwTargetState = MD_SERVER_STATE_STARTED;
  476. dwPendingState = MD_SERVER_STATE_CONTINUING;
  477. break;
  478. case MD_SERVER_COMMAND_PAUSE:
  479. dwTargetState = MD_SERVER_STATE_PAUSED;
  480. dwPendingState = MD_SERVER_STATE_PAUSING;
  481. break;
  482. default:
  483. hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  484. BAIL_ON_FAILURE(hr);
  485. }
  486. hr = IISGetServerState(METADATA_MASTER_ROOT_HANDLE, &dwState);
  487. BAIL_ON_FAILURE(hr);
  488. if (dwState == dwTargetState) {
  489. RRETURN (hr);
  490. }
  491. //
  492. // Write the command to the metabase
  493. //
  494. hr = OpenAdminBaseKey(
  495. _pszServerName,
  496. _pszMetaBasePath,
  497. METADATA_PERMISSION_WRITE,
  498. &_pAdminBase,
  499. &hObjHandle
  500. );
  501. BAIL_ON_FAILURE(hr);
  502. hr = IISClearServerWin32Error(hObjHandle);
  503. BAIL_ON_FAILURE(hr);
  504. hr = IISSetCommand(hObjHandle, dwControl);
  505. BAIL_ON_FAILURE(hr);
  506. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  507. while (dwSleepTotal < MAX_SLEEP_INST) {
  508. hr = IISGetServerState(METADATA_MASTER_ROOT_HANDLE, &dwState);
  509. BAIL_ON_FAILURE(hr);
  510. hrMbNode = 0;
  511. hr = IISGetServerWin32Error(METADATA_MASTER_ROOT_HANDLE, &hrMbNode);
  512. BAIL_ON_FAILURE(hr);
  513. // check to see if we hit the target state
  514. if (dwState != dwPendingState)
  515. {
  516. //
  517. // Done one way or another
  518. //
  519. if (dwState == dwTargetState)
  520. {
  521. break;
  522. }
  523. }
  524. // check to see if there was a Win32 error from the server
  525. if (FAILED(hrMbNode))
  526. {
  527. hr = hrMbNode;
  528. BAIL_ON_FAILURE(hr);
  529. }
  530. //
  531. // Still pending...
  532. //
  533. ::Sleep(SLEEP_INTERVAL);
  534. dwSleepTotal += SLEEP_INTERVAL;
  535. }
  536. if (dwSleepTotal >= MAX_SLEEP_INST)
  537. {
  538. //
  539. // Timed out. If there is a real error in the metabase
  540. // use it, otherwise use a generic timeout error
  541. //
  542. hr = HRESULT_FROM_WIN32(ERROR_SERVICE_REQUEST_TIMEOUT);
  543. }
  544. error :
  545. if (_pAdminBase && hObjHandle) {
  546. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  547. }
  548. RRETURN (hr);
  549. }
  550. HRESULT
  551. CIISServer::IISSetCommand(
  552. METADATA_HANDLE hObjHandle,
  553. DWORD dwControl
  554. )
  555. {
  556. HRESULT hr = S_OK;
  557. DWORD dwBufferSize = sizeof(DWORD);
  558. METADATA_RECORD mdrMDData;
  559. LPBYTE pBuffer = (LPBYTE)&dwControl;
  560. MD_SET_DATA_RECORD(&mdrMDData,
  561. MD_SERVER_COMMAND, // server command
  562. METADATA_VOLATILE,
  563. IIS_MD_UT_SERVER,
  564. DWORD_METADATA,
  565. dwBufferSize,
  566. pBuffer);
  567. hr = _pAdminBase->SetData(
  568. hObjHandle,
  569. L"",
  570. &mdrMDData
  571. );
  572. BAIL_ON_FAILURE(hr);
  573. error:
  574. RRETURN(hr);
  575. }
  576. STDMETHODIMP
  577. CIISServer::ADSIInitializeDispatchManager(
  578. long dwExtensionId
  579. )
  580. {
  581. HRESULT hr = S_OK;
  582. if (_fDispInitialized) {
  583. RRETURN(E_FAIL);
  584. }
  585. hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
  586. if (SUCCEEDED(hr)) {
  587. _fDispInitialized = TRUE;
  588. }
  589. RRETURN(hr);
  590. }
  591. STDMETHODIMP
  592. CIISServer::ADSIInitializeObject(
  593. THIS_ BSTR lpszUserName,
  594. BSTR lpszPassword,
  595. long lnReserved
  596. )
  597. {
  598. CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
  599. _Credentials = NewCredentials;
  600. RRETURN(S_OK);
  601. }
  602. STDMETHODIMP
  603. CIISServer::ADSIReleaseObject()
  604. {
  605. delete this;
  606. RRETURN(S_OK);
  607. }
  608. STDMETHODIMP
  609. CIISServer::NonDelegatingQueryInterface(
  610. REFIID iid,
  611. LPVOID FAR* ppv
  612. )
  613. {
  614. if (IsEqualIID(iid, IID_IADsServiceOperations)) {
  615. *ppv = (IADsUser FAR *) this;
  616. } else if (IsEqualIID(iid, IID_IADsExtension)) {
  617. *ppv = (IADsExtension FAR *) this;
  618. } else if (IsEqualIID(iid, IID_IUnknown)) {
  619. //
  620. // probably not needed since our 3rd party extension does not stand
  621. // alone and provider does not ask for this, but to be safe
  622. //
  623. *ppv = (INonDelegatingUnknown FAR *) this;
  624. } else {
  625. *ppv = NULL;
  626. return E_NOINTERFACE;
  627. }
  628. //
  629. // Delegating AddRef to aggregator for IADsExtesnion and IISServer.
  630. // AddRef on itself for IPrivateUnknown. (both tested.)
  631. //
  632. ((IUnknown *) (*ppv)) -> AddRef();
  633. return S_OK;
  634. }
  635. //
  636. // IADsExtension::Operate()
  637. //
  638. STDMETHODIMP
  639. CIISServer::Operate(
  640. THIS_ DWORD dwCode,
  641. VARIANT varUserName,
  642. VARIANT varPassword,
  643. VARIANT varFlags
  644. )
  645. {
  646. RRETURN(E_NOTIMPL);
  647. }