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.

1174 lines
30 KiB

  1. // admin.cpp : Implementation of CnntpadmApp and DLL registration.
  2. #include "stdafx.h"
  3. #include "nntpcmn.h"
  4. #include "oleutil.h"
  5. #include "cmultisz.h"
  6. #include "metautil.h"
  7. #include "metakey.h"
  8. #include "admin.h"
  9. #include "version.h"
  10. #define NNTP_DEF_SERVICE_VERSION ( 0 )
  11. #define DEFAULT_SERVER_BINDINGS _T(":119:\0")
  12. #define DEFAULT_SECURE_BINDINGS _T(":563:\0")
  13. // Must define THIS_FILE_* macros to use NntpCreateException()
  14. #define THIS_FILE_HELP_CONTEXT 0
  15. #define THIS_FILE_PROG_ID _T("Nntpadm.Admin.1")
  16. #define THIS_FILE_IID IID_INntpAdmin
  17. //
  18. // Metabase key strings used by CreateNewInstance:
  19. //
  20. const WCHAR * g_cszFeeds = _T("Feeds");
  21. const WCHAR * g_cszExpires = _T("Expires");
  22. const WCHAR * g_cszRoot = _T("Root");
  23. const WCHAR * g_cszBindingPoints = _T("BindingPoints");
  24. const WCHAR * g_cszDDropCLSID = _T("{8b4316f4-af73-11d0-b0ba-00aa00c148be}");
  25. const WCHAR * g_cszBindings = _T("Bindings");
  26. const WCHAR * g_cszDDrop = _T("ddrop");
  27. const WCHAR * g_cszDescription = _T("Description");
  28. const WCHAR * g_cszPriority = _T("Priority");
  29. const WCHAR * g_cszProgID = _T("ProgID");
  30. const WCHAR * g_cszDDropDescription = _T("NNTP Directory Drop");
  31. const WCHAR * g_cszDDropPriority = _T("4");
  32. const WCHAR * g_cszDDropProgID = _T("DDropNNTP.Filter");
  33. /////////////////////////////////////////////////////////////////////////////
  34. //
  35. CNntpAdmin::CNntpAdmin () :
  36. m_dwServiceVersion ( 0 ),
  37. m_dwServiceInstance ( 0 )
  38. // CComBSTR's are initialized to NULL by default.
  39. {
  40. InitAsyncTrace ( );
  41. }
  42. CNntpAdmin::~CNntpAdmin ()
  43. {
  44. // All CComBSTR's are freed automatically.
  45. TermAsyncTrace ( );
  46. }
  47. STDMETHODIMP CNntpAdmin::InterfaceSupportsErrorInfo(REFIID riid)
  48. {
  49. static const IID* arr[] =
  50. {
  51. &IID_INntpAdmin,
  52. };
  53. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  54. {
  55. if (InlineIsEqualGUID(*arr[i],riid))
  56. return S_OK;
  57. }
  58. return S_FALSE;
  59. }
  60. /*
  61. STDMETHODIMP CNntpAdmin::get_ServiceAdmin ( IDispatch ** ppIDispatch )
  62. {
  63. HRESULT hr = NOERROR;
  64. CComPtr<INntpService> pINntpService;
  65. hr = StdPropertyHandoffIDispatch (
  66. CLSID_CNntpService,
  67. IID_INntpService,
  68. &pINntpService,
  69. ppIDispatch
  70. );
  71. if ( FAILED(hr) ) {
  72. goto Error;
  73. }
  74. // Set default properties:
  75. hr = pINntpService->put_Server ( m_strServer ? m_strServer : _T("") );
  76. if ( FAILED (hr) ) {
  77. goto Error;
  78. }
  79. return hr;
  80. Error:
  81. SAFE_RELEASE ( *ppIDispatch );
  82. *ppIDispatch = NULL;
  83. return hr;
  84. // Destructor releases pINntpAdminExpiration
  85. }
  86. */
  87. STDMETHODIMP CNntpAdmin::get_ServerAdmin ( IDispatch ** ppIDispatch )
  88. {
  89. HRESULT hr = NOERROR;
  90. CComPtr<INntpVirtualServer> pINntpVirtualServer;
  91. CComBSTR strTemp = _T("");
  92. if (!strTemp)
  93. {
  94. hr = E_OUTOFMEMORY;
  95. goto Error;
  96. }
  97. hr = StdPropertyHandoffIDispatch (
  98. CLSID_CNntpVirtualServer,
  99. IID_INntpVirtualServer,
  100. &pINntpVirtualServer,
  101. ppIDispatch
  102. );
  103. if ( FAILED(hr) ) {
  104. goto Error;
  105. }
  106. // Set default properties:
  107. hr = pINntpVirtualServer->put_Server ( m_strServer ? m_strServer : strTemp );
  108. if ( FAILED (hr) ) {
  109. goto Error;
  110. }
  111. hr = pINntpVirtualServer->put_ServiceInstance ( m_dwServiceInstance );
  112. if ( FAILED (hr) ) {
  113. goto Error;
  114. }
  115. return hr;
  116. Error:
  117. SAFE_RELEASE ( *ppIDispatch );
  118. *ppIDispatch = NULL;
  119. return hr;
  120. // Destructor releases pINntpVirtualServer
  121. }
  122. // Which service to configure:
  123. STDMETHODIMP CNntpAdmin::get_Server ( BSTR * pstrServer )
  124. {
  125. return StdPropertyGet ( m_strServer, pstrServer );
  126. }
  127. STDMETHODIMP CNntpAdmin::put_Server ( BSTR strServer )
  128. {
  129. return StdPropertyPutServerName ( &m_strServer, strServer );
  130. }
  131. STDMETHODIMP CNntpAdmin::get_ServiceInstance ( long * plServiceInstance )
  132. {
  133. return StdPropertyGet ( m_dwServiceInstance, plServiceInstance );
  134. }
  135. STDMETHODIMP CNntpAdmin::put_ServiceInstance ( long lServiceInstance )
  136. {
  137. return StdPropertyPut ( &m_dwServiceInstance, lServiceInstance );
  138. }
  139. // Versioning:
  140. STDMETHODIMP CNntpAdmin::get_HighVersion ( long * plHighVersion )
  141. {
  142. *plHighVersion = HIGH_VERSION;
  143. return NOERROR;
  144. }
  145. STDMETHODIMP CNntpAdmin::get_LowVersion ( long * plLowVersion )
  146. {
  147. *plLowVersion = LOW_VERSION;
  148. return NOERROR;
  149. }
  150. STDMETHODIMP CNntpAdmin::get_BuildNum ( long * plBuildNumber )
  151. {
  152. *plBuildNumber = CURRENT_BUILD_NUMBER;
  153. return NOERROR;
  154. }
  155. STDMETHODIMP CNntpAdmin::get_ServiceVersion ( long * plServiceVersion )
  156. {
  157. *plServiceVersion = m_dwServiceVersion;
  158. return NOERROR;
  159. }
  160. //////////////////////////////////////////////////////////////////////
  161. // Methods:
  162. //////////////////////////////////////////////////////////////////////
  163. //$-------------------------------------------------------------------
  164. //
  165. // CNntpAdmin::EnumerateInstances
  166. //
  167. // Description:
  168. //
  169. // Returns a list of the virtual servers on the given machine.
  170. //
  171. // Parameters:
  172. //
  173. // ppsaInstances - Returned SAFEARRAY of instance IDs.
  174. // Must be freed by caller.
  175. // pErr - Error return code.
  176. //
  177. // Returns:
  178. //
  179. // Error code in *pErr.
  180. //
  181. //--------------------------------------------------------------------
  182. STDMETHODIMP CNntpAdmin::EnumerateInstances ( SAFEARRAY ** ppsaInstances)
  183. {
  184. TraceFunctEnter ( "CNntpAdmin::EnumerateInstances" );
  185. HRESULT hr = NOERROR;
  186. CComPtr<IMSAdminBase> pMetabase;
  187. SAFEARRAY * psaEmpty = NULL;
  188. SAFEARRAYBOUND sabound[1];
  189. // Check parameters:
  190. _ASSERT ( ppsaInstances != NULL );
  191. _ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
  192. if ( ppsaInstances == NULL ) {
  193. FatalTrace ( 0, "Bad return pointer" );
  194. hr = E_POINTER;
  195. goto Exit;
  196. }
  197. // Zero the out parameters:
  198. *ppsaInstances = NULL;
  199. // Set the return array to an empty array:
  200. sabound[0].lLbound = 0;
  201. sabound[0].cElements = 0;
  202. psaEmpty = SafeArrayCreate ( VT_I4, 1, sabound );
  203. if ( psaEmpty == NULL ) {
  204. FatalTrace ( (LPARAM) this, "Out of memory" );
  205. hr = E_OUTOFMEMORY;
  206. goto Exit;
  207. }
  208. *ppsaInstances = psaEmpty;
  209. // Get the metabase pointer:
  210. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  211. if ( FAILED(hr) ) {
  212. goto Exit;
  213. }
  214. // Enumerate the instances:
  215. hr = QueryMetabaseInstances ( pMetabase, ppsaInstances );
  216. if ( FAILED(hr) ) {
  217. goto Exit;
  218. }
  219. Exit:
  220. if ( FAILED(hr) ) {
  221. _VERIFY ( SUCCEEDED (SafeArrayDestroy ( psaEmpty )) );
  222. if (ppsaInstances)
  223. *ppsaInstances = NULL;
  224. }
  225. TRACE_HRESULT ( hr );
  226. TraceFunctLeave ();
  227. return hr;
  228. }
  229. STDMETHODIMP CNntpAdmin::EnumerateInstancesVariant ( SAFEARRAY ** ppsaInstances)
  230. {
  231. TraceFunctEnter ( "CNntpAdmin::EnumerateInstancesVariant" );
  232. HRESULT hr;
  233. SAFEARRAY * psaInstances = NULL;
  234. hr = EnumerateInstances ( &psaInstances );
  235. BAIL_ON_FAILURE(hr);
  236. hr = LongArrayToVariantArray ( psaInstances, ppsaInstances );
  237. BAIL_ON_FAILURE(hr);
  238. Exit:
  239. TraceFunctLeave ();
  240. return hr;
  241. }
  242. //$-------------------------------------------------------------------
  243. //
  244. // CNntpAdmin::CreateInstance
  245. //
  246. // Description:
  247. //
  248. // Creates a new NNTP virtual server on the given machine.
  249. //
  250. // Parameters:
  251. //
  252. // strNntpFileDirectory - Directory where all the hash files go.
  253. // strHomeDirectory - Path of the home directory vroot.
  254. // plInstanceId - The new virtual server ID.
  255. // pErr - Resulting error code.
  256. //
  257. // Returns:
  258. //
  259. // Error condition in *pErr.
  260. //
  261. //--------------------------------------------------------------------
  262. STDMETHODIMP CNntpAdmin::CreateInstance (
  263. BSTR strNntpFileDirectory,
  264. BSTR strHomeDirectory,
  265. BSTR strProgId,
  266. BSTR strMdbGuid,
  267. long * plInstanceId
  268. )
  269. {
  270. TraceFunctEnter ( "CNntpAdmin::CreateInstance" );
  271. HRESULT hr = NOERROR;
  272. CComPtr<IMSAdminBase> pMetabase;
  273. // Check parameters:
  274. _ASSERT ( IS_VALID_STRING ( strNntpFileDirectory ) );
  275. _ASSERT ( IS_VALID_STRING ( strHomeDirectory ) );
  276. _ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
  277. if ( !strNntpFileDirectory || !strHomeDirectory ) {
  278. FatalTrace ( 0, "Bad String Pointer" );
  279. hr = E_POINTER;
  280. goto Exit;
  281. }
  282. if ( !plInstanceId ) {
  283. FatalTrace ( 0, "Bad return pointer" );
  284. hr = E_POINTER;
  285. goto Exit;
  286. }
  287. // Zero the out parameter:
  288. *plInstanceId = 0;
  289. // Get the metabase pointer:
  290. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  291. if ( FAILED(hr) ) {
  292. goto Exit;
  293. }
  294. // Create a new instance:
  295. hr = CreateNewInstance (
  296. pMetabase,
  297. strNntpFileDirectory,
  298. strHomeDirectory,
  299. strProgId,
  300. strMdbGuid,
  301. plInstanceId
  302. );
  303. if ( FAILED(hr) ) {
  304. goto Exit;
  305. }
  306. Exit:
  307. TRACE_HRESULT(hr);
  308. TraceFunctLeave ();
  309. return hr;
  310. }
  311. //$-------------------------------------------------------------------
  312. //
  313. // CNntpAdmin::DestroyInstance
  314. //
  315. // Description:
  316. //
  317. // Removes the given virtual server.
  318. //
  319. // Parameters:
  320. //
  321. // lInstanceId - The ID of the virtual server to delete.
  322. // pErr - Resulting error code.
  323. //
  324. // Returns:
  325. //
  326. // Error code in *pErr.
  327. //
  328. //--------------------------------------------------------------------
  329. STDMETHODIMP CNntpAdmin::DestroyInstance ( long lInstanceId )
  330. {
  331. TraceFunctEnter ( "CNntpAdmin::DestroyInstance" );
  332. HRESULT hr = NOERROR;
  333. CComPtr<IMSAdminBase> pMetabase;
  334. if ( lInstanceId == 0 ) {
  335. hr = NntpCreateException ( IDS_NNTPEXCEPTION_SERVICE_INSTANCE_CANT_BE_ZERO );
  336. goto Exit;
  337. }
  338. if ( lInstanceId == 1 ) {
  339. hr = NntpCreateException ( IDS_NNTPEXCEPTION_CANT_DELETE_DEFAULT_INSTANCE );
  340. goto Exit;
  341. }
  342. // Get the metabase pointer:
  343. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  344. if ( FAILED(hr) ) {
  345. goto Exit;
  346. }
  347. // Delete the instance:
  348. hr = DeleteInstance ( pMetabase, lInstanceId );
  349. if ( FAILED(hr) ) {
  350. goto Exit;
  351. }
  352. Exit:
  353. TRACE_HRESULT(hr);
  354. TraceFunctLeave ();
  355. return hr;
  356. }
  357. //$-------------------------------------------------------------------
  358. //
  359. // CNntpAdmin::ErrorToString
  360. //
  361. // Description:
  362. //
  363. // Translates an NNTP_ERROR_CODE to a readable string.
  364. //
  365. // Parameters:
  366. //
  367. // lErrorCode - Win32 error code.
  368. // pstrError - the readable error string.
  369. //
  370. // Returns:
  371. //
  372. // The error string in *pstrError.
  373. //
  374. //--------------------------------------------------------------------
  375. STDMETHODIMP CNntpAdmin::ErrorToString ( long lErrorCode, BSTR * pstrError )
  376. {
  377. TraceFunctEnter ( "CNntpAdmin::ErrorToString" );
  378. _ASSERT ( IS_VALID_OUT_PARAM ( pstrError ) );
  379. HRESULT hr = NOERROR;
  380. WCHAR wszError [ 1024 ];
  381. if ( pstrError == NULL ) {
  382. FatalTrace ( (LPARAM) this, "Bad return pointer" );
  383. hr = E_POINTER;
  384. goto Exit;
  385. }
  386. Win32ErrorToString ( lErrorCode, wszError, 1024 );
  387. *pstrError = ::SysAllocString( wszError );
  388. if ( *pstrError == NULL ) {
  389. hr = E_OUTOFMEMORY;
  390. goto Exit;
  391. }
  392. Exit:
  393. TRACE_HRESULT(hr);
  394. TraceFunctLeave ();
  395. return hr;
  396. }
  397. //$-------------------------------------------------------------------
  398. //
  399. // CNntpAdmin::Tokenize
  400. //
  401. // Description:
  402. //
  403. // Makes the given string safe for HTML & Javascript
  404. //
  405. // Parameters:
  406. //
  407. // strIn - the input string
  408. // strOut - the resulting string with appropriate escape sequences.
  409. //
  410. //--------------------------------------------------------------------
  411. STDMETHODIMP CNntpAdmin::Tokenize ( BSTR strIn, BSTR * pstrOut )
  412. {
  413. TraceFunctEnter ( "CNntpAdmin::Tokenize" );
  414. _ASSERT ( IS_VALID_STRING ( strIn ) );
  415. _ASSERT ( IS_VALID_OUT_PARAM ( pstrOut ) );
  416. HRESULT hr = NOERROR;
  417. PWCHAR pSrc = strIn;
  418. PWCHAR pSrcCur = NULL;
  419. PWCHAR pDstCur = NULL;
  420. PWCHAR pDst = NULL;
  421. *pstrOut = NULL;
  422. pDst = new WCHAR [ 3 * lstrlen ( strIn ) + 1 ];
  423. if ( pDst == NULL ) {
  424. FatalTrace ( (LPARAM) this, "Out of memory" );
  425. hr = E_OUTOFMEMORY;
  426. goto Exit;
  427. }
  428. for ( pSrcCur = pSrc, pDstCur = pDst; *pSrcCur; pSrcCur++ ) {
  429. switch ( *pSrcCur ) {
  430. case L'\\':
  431. *(pDstCur++) = L'%';
  432. *(pDstCur++) = L'5';
  433. *(pDstCur++) = L'c';
  434. break;
  435. case L' ':
  436. *(pDstCur++) = L'+';
  437. break;
  438. case L':':
  439. *(pDstCur++) = L'%';
  440. *(pDstCur++) = L'3';
  441. *(pDstCur++) = L'a';
  442. break;
  443. case L'/':
  444. *(pDstCur++) = L'%';
  445. *(pDstCur++) = L'2';
  446. *(pDstCur++) = L'f';
  447. break;
  448. default:
  449. *(pDstCur++) = *pSrcCur;
  450. }
  451. }
  452. *pDstCur = L'\0';
  453. *pstrOut = ::SysAllocString ( pDst );
  454. if ( *pstrOut == NULL ) {
  455. FatalTrace ( (LPARAM) this, "Out of memory" );
  456. hr = E_OUTOFMEMORY;
  457. goto Exit;
  458. }
  459. Exit:
  460. delete pDst;
  461. TRACE_HRESULT(hr);
  462. TraceFunctLeave ();
  463. return hr;
  464. }
  465. //$-------------------------------------------------------------------
  466. //
  467. // CNntpAdmin::Truncate
  468. //
  469. // Description:
  470. //
  471. // Cuts off a string to a certain length using '...'
  472. //
  473. // Parameters:
  474. //
  475. // strIn - The input string.
  476. // cMaxChars - The maximum characters allowed in the resulting string.
  477. // pstrOut - The resulting (possibly truncated) string.
  478. //
  479. // Returns:
  480. //
  481. //
  482. //
  483. //--------------------------------------------------------------------
  484. STDMETHODIMP CNntpAdmin::Truncate ( BSTR strIn, long cMaxChars, BSTR * pstrOut )
  485. {
  486. TraceFunctEnter ( "CNntpAdmin::Truncate" );
  487. PWCHAR pSrc = strIn;
  488. PWCHAR pDst = NULL;
  489. DWORD cDst = cMaxChars;
  490. HRESULT hr = NOERROR;
  491. *pstrOut = NULL;
  492. if ( wcslen( pSrc ) <= cDst ) {
  493. pDst = pSrc;
  494. } else {
  495. pDst = ::SysAllocStringLen( pSrc, cDst + 1 );
  496. if ( !pDst ) {
  497. FatalTrace ( (LPARAM) this, "Out of memory" );
  498. hr = E_OUTOFMEMORY;
  499. goto Exit;
  500. }
  501. wcscpy( pDst + cDst - 3, L"..." );
  502. }
  503. *pstrOut = pDst;
  504. Exit:
  505. TRACE_HRESULT(hr);
  506. TraceFunctLeave ();
  507. return hr;
  508. }
  509. //$-------------------------------------------------------------------
  510. //
  511. // CNntpAdmin::QueryMetabaseInstances
  512. //
  513. // Description:
  514. //
  515. // Retrieves the list of virtual servers from the metabase
  516. //
  517. // Parameters:
  518. //
  519. // pMetabase - the metabase object
  520. // ppsaInstances - resulting array of instance ids.
  521. // pErr - resulting error code.
  522. //
  523. // Returns:
  524. //
  525. // Error code in *pErr. If *pErr = 0 then an array of IDs in ppsaInstances.
  526. //
  527. //--------------------------------------------------------------------
  528. HRESULT CNntpAdmin::QueryMetabaseInstances ( IMSAdminBase * pMetabase, SAFEARRAY ** ppsaInstances )
  529. {
  530. TraceFunctEnter ( "CNntpAdmin::QueryMetabaseInstances" );
  531. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  532. _ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
  533. HRESULT hr = NOERROR;
  534. CMetabaseKey mkeyNntp ( pMetabase );
  535. SAFEARRAY * psaResult = NULL;
  536. DWORD cValidInstances = 0;
  537. SAFEARRAYBOUND rgsaBound[1];
  538. DWORD i;
  539. WCHAR wszName[ METADATA_MAX_NAME_LEN ];
  540. long index[1];
  541. DWORD dwInstance;
  542. hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH );
  543. if ( FAILED(hr) ) {
  544. ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", hr );
  545. hr = HRESULT_FROM_WIN32 ( ERROR_SERVICE_DOES_NOT_EXIST );
  546. goto Exit;
  547. }
  548. // pickup the service version number:
  549. hr = mkeyNntp.GetDword ( MD_NNTP_SERVICE_VERSION, &m_dwServiceVersion );
  550. if ( FAILED(hr) ) {
  551. m_dwServiceVersion = NNTP_DEF_SERVICE_VERSION;
  552. }
  553. hr = mkeyNntp.GetIntegerChildCount ( &cValidInstances );
  554. if ( FAILED(hr) ) {
  555. goto Exit;
  556. }
  557. // Allocate the array:
  558. rgsaBound[0].lLbound = 0;
  559. rgsaBound[0].cElements = cValidInstances;
  560. psaResult = SafeArrayCreate ( VT_I4, 1, rgsaBound );
  561. if ( psaResult == NULL ) {
  562. FatalTrace ( 0, "Out of memory" );
  563. hr = E_OUTOFMEMORY;
  564. goto Exit;
  565. }
  566. mkeyNntp.BeginChildEnumeration ();
  567. for ( i = 0; i < cValidInstances; i++ ) {
  568. hr = mkeyNntp.NextIntegerChild ( &dwInstance, wszName );
  569. _ASSERT ( SUCCEEDED(hr) );
  570. index[0] = i;
  571. hr = SafeArrayPutElement ( psaResult, index, &dwInstance );
  572. _ASSERT ( SUCCEEDED(hr) );
  573. }
  574. *ppsaInstances = psaResult;
  575. _ASSERT ( SUCCEEDED(hr) );
  576. Exit:
  577. if ( FAILED (hr) ) {
  578. SafeArrayDestroy ( psaResult );
  579. }
  580. TraceFunctLeave ();
  581. return hr;
  582. }
  583. HRESULT WriteNntpFileLocation (
  584. CMetabaseKey * pmkeyNntp,
  585. LPCWSTR wszSubkey,
  586. LPCWSTR wszNntpFileDirectory,
  587. LPCWSTR wszFilename,
  588. DWORD mdValue
  589. )
  590. {
  591. HRESULT hr;
  592. WCHAR wszFullPath [ MAX_PATH ];
  593. if (wcslen( wszNntpFileDirectory )+1+wcslen( wszFilename )+1 > MAX_PATH )
  594. return HRESULT_FROM_WIN32 ( ERROR_FILENAME_EXCED_RANGE );
  595. wsprintf ( wszFullPath, _T("%s\\%s"), wszNntpFileDirectory, wszFilename );
  596. hr = pmkeyNntp->SetString ( wszSubkey, mdValue, wszFullPath );
  597. return hr;
  598. }
  599. //$-------------------------------------------------------------------
  600. // CNntpAdmin::CreateVRoot
  601. //
  602. // Description:
  603. //
  604. // Create a vroot for the new instance
  605. //
  606. // Parameters:
  607. //
  608. // CMetabaseKey &mkeyNntp - The metabase key object
  609. // BSTR strVPath - The vroot path
  610. // BSTR strProgId - The prog id to identify vroot type
  611. // LPWSTR wszKeyPath - The key path to set values to
  612. //
  613. // Returns:
  614. //
  615. // HRESULT
  616. //
  617. //--------------------------------------------------------------------
  618. HRESULT CNntpAdmin::CreateVRoot(
  619. CMetabaseKey &mkeyNntp,
  620. BSTR strVPath,
  621. BSTR strProgId,
  622. BSTR strMdbGuid,
  623. LPWSTR wszKeyPath
  624. )
  625. {
  626. TraceFunctEnter( "CNntpAdmin::CreateVRoot" );
  627. HRESULT hr = S_OK;
  628. hr = mkeyNntp.SetString ( wszKeyPath, MD_KEY_TYPE, L"IIsNntpVirtualDir", METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER);
  629. BAIL_ON_FAILURE(hr);
  630. hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_PATH, strVPath );
  631. BAIL_ON_FAILURE(hr);
  632. if ( NULL == strProgId || *strProgId == 0 || _wcsicmp( strProgId, L"NNTP.FSPrepare" ) == 0 ) {
  633. //
  634. // File system driver case
  635. //
  636. hr = mkeyNntp.SetString ( wszKeyPath, MD_FS_PROPERTY_PATH, strVPath );
  637. BAIL_ON_FAILURE(hr);
  638. if ( *strVPath == L'\\' && *(strVPath+1) == L'\\' ) { // UNC
  639. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 1 );
  640. BAIL_ON_FAILURE( hr );
  641. } else { // regular file system
  642. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 0 );
  643. }
  644. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_DO_EXPIRE, 0 );
  645. BAIL_ON_FAILURE( hr );
  646. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_OWN_MODERATOR, 0 );
  647. BAIL_ON_FAILURE( hr );
  648. } else {
  649. //
  650. // Exchange store driver
  651. //
  652. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_USE_ACCOUNT, 0 );
  653. BAIL_ON_FAILURE( hr );
  654. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_DO_EXPIRE, 1 );
  655. BAIL_ON_FAILURE( hr );
  656. hr = mkeyNntp.SetDword( wszKeyPath, MD_VR_OWN_MODERATOR, 1 );
  657. BAIL_ON_FAILURE( hr );
  658. hr = mkeyNntp.SetString( wszKeyPath, MD_EX_MDB_GUID, strMdbGuid );
  659. BAIL_ON_FAILURE( hr );
  660. }
  661. if (NULL == strProgId || *strProgId == 0) {
  662. hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_DRIVER_PROGID, L"NNTP.FSPrepare" );
  663. } else {
  664. hr = mkeyNntp.SetString ( wszKeyPath, MD_VR_DRIVER_PROGID, strProgId );
  665. }
  666. BAIL_ON_FAILURE(hr);
  667. hr = mkeyNntp.SetDword ( wszKeyPath, MD_ACCESS_PERM, MD_ACCESS_READ | MD_ACCESS_WRITE );
  668. BAIL_ON_FAILURE(hr);
  669. Exit:
  670. TraceFunctLeave();
  671. return hr;
  672. }
  673. //$-------------------------------------------------------------------
  674. //
  675. // CNntpAdmin::CreateNewInstance
  676. //
  677. // Description:
  678. //
  679. // Creates a new virtual server in the metabase.
  680. //
  681. // Parameters:
  682. //
  683. // pMetabase - The metabase object
  684. // plInstanceId - The new instance ID.
  685. // pErr - The resulting error code
  686. //
  687. // Returns:
  688. //
  689. // Resulting error code in *pErr. If *pErr = 0, then the new
  690. // ID in plInstanceId.
  691. //
  692. //--------------------------------------------------------------------
  693. HRESULT CNntpAdmin::CreateNewInstance (
  694. IMSAdminBase * pMetabase,
  695. BSTR strNntpFileDirectory,
  696. BSTR strHomeDirectory,
  697. BSTR strProgId,
  698. BSTR strMdbGuid,
  699. long * plInstanceId
  700. )
  701. {
  702. TraceFunctEnter ( "CNntpAdmin::CreateNewInstance" );
  703. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  704. _ASSERT ( IS_VALID_IN_PARAM ( strNntpFileDirectory ) );
  705. _ASSERT ( IS_VALID_IN_PARAM ( strHomeDirectory ) );
  706. _ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
  707. HRESULT hr = NOERROR;
  708. CMetabaseKey mkeyNntp ( pMetabase );
  709. DWORD dwInstance;
  710. WCHAR wszInstance [ METADATA_MAX_NAME_LEN ];
  711. WCHAR wszHomeDirKey [ METADATA_MAX_NAME_LEN ];
  712. WCHAR wszSpecialDirKey[ METADATA_MAX_NAME_LEN ];
  713. WCHAR wszSpecialDirectory[ MAX_PATH * 2 ];
  714. WCHAR wszControlDirKey [ METADATA_MAX_NAME_LEN ];
  715. WCHAR wszControlDirectory[ MAX_PATH * 2 ];
  716. WCHAR wszBuf [ METADATA_MAX_NAME_LEN * 2 ];
  717. WCHAR wszFeedTempDir [ MAX_PATH * 2 ];
  718. CMultiSz mszBindings;
  719. DWORD dwLen;
  720. // Zero the out parameter:
  721. *plInstanceId = NULL;
  722. mszBindings = DEFAULT_SERVER_BINDINGS;
  723. //
  724. // Convert strings to ascii:
  725. //
  726. if (lstrlen(strNntpFileDirectory)+1>MAX_PATH)
  727. {
  728. HRESULT_FROM_WIN32 ( ERROR_FILENAME_EXCED_RANGE );
  729. goto Exit;
  730. }
  731. hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
  732. if ( FAILED(hr) ) {
  733. ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", hr );
  734. goto Exit;
  735. }
  736. hr = mkeyNntp.CreateIntegerChild ( &dwInstance, wszInstance );
  737. if ( FAILED (hr) ) {
  738. goto Exit;
  739. }
  740. //
  741. // Write out the subkeys of the instance key:
  742. //
  743. wsprintf ( wszBuf, _T("%s/%s"), wszInstance, g_cszFeeds );
  744. hr = mkeyNntp.CreateChild ( wszBuf );
  745. BAIL_ON_FAILURE ( hr );
  746. wsprintf ( wszFeedTempDir, _T("%s\\%s"), strNntpFileDirectory, _T("_temp.files_") );
  747. mkeyNntp.SetString ( wszBuf, MD_FEED_PEER_TEMP_DIRECTORY, wszFeedTempDir );
  748. BAIL_ON_FAILURE ( hr );
  749. wsprintf ( wszBuf, _T("%s/%s"), wszInstance, g_cszExpires );
  750. hr = mkeyNntp.CreateChild ( wszBuf );
  751. BAIL_ON_FAILURE ( hr );
  752. wsprintf ( wszHomeDirKey, _T("%s/%s"), wszInstance, g_cszRoot );
  753. hr = mkeyNntp.CreateChild ( wszHomeDirKey );
  754. BAIL_ON_FAILURE ( hr );
  755. //
  756. // Set MD_KEY_TYPE for each key:
  757. //
  758. hr = mkeyNntp.SetString ( wszInstance, MD_KEY_TYPE, _T("IIsNntpServer"), METADATA_NO_ATTRIBUTES );
  759. BAIL_ON_FAILURE ( hr );
  760. hr = mkeyNntp.SetString ( wszHomeDirKey, MD_KEY_TYPE, _T("IIsNntpVirtualDir"), METADATA_NO_ATTRIBUTES );
  761. BAIL_ON_FAILURE(hr);
  762. //
  763. // Write out the file locations:
  764. //
  765. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("descrip.txt"), MD_GROUP_HELP_FILE );
  766. BAIL_ON_FAILURE(hr);
  767. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("group.lst"), MD_GROUP_LIST_FILE );
  768. BAIL_ON_FAILURE(hr);
  769. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("groupvar.lst"), MD_GROUPVAR_LIST_FILE );
  770. BAIL_ON_FAILURE(hr);
  771. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("article.hsh"), MD_ARTICLE_TABLE_FILE );
  772. BAIL_ON_FAILURE(hr);
  773. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("history.hsh"), MD_HISTORY_TABLE_FILE );
  774. BAIL_ON_FAILURE(hr);
  775. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("moderatr.txt"), MD_MODERATOR_FILE );
  776. BAIL_ON_FAILURE(hr);
  777. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("xover.hsh"), MD_XOVER_TABLE_FILE );
  778. BAIL_ON_FAILURE(hr);
  779. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("pickup"), MD_PICKUP_DIRECTORY );
  780. BAIL_ON_FAILURE(hr);
  781. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("failedpickup"), MD_FAILED_PICKUP_DIRECTORY );
  782. BAIL_ON_FAILURE(hr);
  783. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("drop"), MD_DROP_DIRECTORY );
  784. BAIL_ON_FAILURE(hr);
  785. hr = WriteNntpFileLocation ( &mkeyNntp, wszInstance, strNntpFileDirectory, _T("prettynm.txt"), MD_PRETTYNAMES_FILE);
  786. BAIL_ON_FAILURE(hr);
  787. //
  788. // Set the default vroot:
  789. //
  790. dwLen = wcslen( wszHomeDirKey );
  791. _ASSERT( dwLen > 0 );
  792. if ( dwLen == 0 ) hr = E_INVALIDARG;
  793. BAIL_ON_FAILURE(hr);
  794. hr = CreateVRoot( mkeyNntp,
  795. strHomeDirectory,
  796. strProgId,
  797. strMdbGuid,
  798. wszHomeDirKey );
  799. BAIL_ON_FAILURE(hr);
  800. //
  801. // Set the special vroots
  802. //
  803. if ( dwLen + wcslen(L"_slavegroup") >= METADATA_MAX_NAME_LEN - 2 )
  804. hr = HRESULT_FROM_WIN32( RPC_S_STRING_TOO_LONG );
  805. BAIL_ON_FAILURE(hr);
  806. if ( *(wszHomeDirKey + dwLen - 1 ) == L'/' ) *(wszHomeDirKey + dwLen - 1 ) = 0;
  807. wcscpy(wszControlDirKey, wszHomeDirKey);
  808. wcscat(wszControlDirKey, L"/control");
  809. wcscat( wszHomeDirKey, L"/_slavegroup" );
  810. //
  811. // For the special _slavegroup vroot, we need to see if strProgId is "NNTP.ExDriverPrepare"
  812. // If so, we need to re-calculate re-calculate wszSpecialDirectory as follow
  813. //
  814. if (_wcsicmp(L"NNTP.ExDriverPrepare", strProgId) == 0)
  815. {
  816. // the default Vroot with the new instance is Exchange Vroot
  817. // re-calculate wszSpecialDirectory
  818. wcscpy( wszSpecialDirectory, strNntpFileDirectory );
  819. dwLen = wcslen( wszSpecialDirectory );
  820. if ( dwLen > 0 && *(wszSpecialDirectory + dwLen - 1 ) == L'/' )
  821. *(wszSpecialDirectory + dwLen - 1 ) = 0;
  822. wcscpy(wszControlDirectory, wszSpecialDirectory);
  823. wcscat( wszControlDirectory, L"\\root\\control" );
  824. wcscat( wszSpecialDirectory, L"\\root\\_slavegroup" );
  825. }
  826. else
  827. {
  828. wcscpy( wszSpecialDirectory, strHomeDirectory );
  829. dwLen = wcslen( wszSpecialDirectory );
  830. if ( dwLen > 0 && *(wszSpecialDirectory + dwLen - 1 ) == L'/' )
  831. *(wszSpecialDirectory + dwLen - 1 ) = 0;
  832. wcscpy(wszControlDirectory, wszSpecialDirectory);
  833. wcscat( wszControlDirectory, L"\\control" );
  834. wcscat( wszSpecialDirectory, L"\\_slavegroup" );
  835. }
  836. hr = CreateVRoot( mkeyNntp,
  837. wszSpecialDirectory,
  838. L"NNTP.FSPrepare",
  839. NULL,
  840. wszHomeDirKey );
  841. BAIL_ON_FAILURE(hr);
  842. //
  843. // Create the control groups on the file system
  844. //
  845. hr = CreateVRoot( mkeyNntp,
  846. wszControlDirectory,
  847. L"NNTP.FSPrepare",
  848. NULL,
  849. wszControlDirKey );
  850. BAIL_ON_FAILURE(hr);
  851. //
  852. // Write out the default bindings:
  853. //
  854. StdPutMetabaseProp ( &mkeyNntp, MD_SERVER_BINDINGS, &mszBindings, wszInstance );
  855. //
  856. // Initialize the server state:
  857. //
  858. mkeyNntp.SetDword ( wszInstance, MD_SERVER_COMMAND, MD_SERVER_COMMAND_STOP );
  859. mkeyNntp.SetDword ( wszInstance, MD_SERVER_STATE, MD_SERVER_STATE_STOPPED );
  860. mkeyNntp.SetDword ( wszInstance, MD_SERVER_AUTOSTART, FALSE );
  861. mkeyNntp.SetDword ( wszInstance, MD_WIN32_ERROR, ERROR_SERVICE_REQUEST_TIMEOUT, METADATA_VOLATILE );
  862. //
  863. // Save all the changes:
  864. //
  865. hr = mkeyNntp.Save ( );
  866. BAIL_ON_FAILURE(hr)
  867. mkeyNntp.Close ();
  868. //
  869. // Now see if the service picked things up successfully:
  870. //
  871. DWORD dwSleepTotal;
  872. DWORD dwWin32Error;
  873. WCHAR wszNewInstanceKey [ METADATA_MAX_NAME_LEN * 2 ];
  874. GetMDInstancePath ( wszNewInstanceKey, dwInstance );
  875. for ( dwWin32Error = ERROR_SERVICE_REQUEST_TIMEOUT, dwSleepTotal = 0;
  876. dwWin32Error == ERROR_SERVICE_REQUEST_TIMEOUT && dwSleepTotal < MAX_SLEEP_INST;
  877. dwSleepTotal += SLEEP_INTERVAL
  878. ) {
  879. HRESULT hr2;
  880. Sleep ( SLEEP_INTERVAL );
  881. hr2 = mkeyNntp.Open ( wszNewInstanceKey );
  882. _ASSERT ( SUCCEEDED(hr2) );
  883. hr2 = mkeyNntp.GetDword ( MD_WIN32_ERROR, &dwWin32Error );
  884. _ASSERT ( SUCCEEDED(hr2) );
  885. }
  886. if ( dwWin32Error != NOERROR ) {
  887. HRESULT hr2;
  888. //
  889. // The service reported an error.
  890. // Delete the new instance key
  891. //
  892. hr2 = mkeyNntp.Open ( NNTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
  893. _ASSERT ( SUCCEEDED(hr2) );
  894. hr2 = mkeyNntp.DestroyChild ( wszInstance );
  895. _ASSERT ( SUCCEEDED(hr2) );
  896. hr2 = mkeyNntp.Save ();
  897. _ASSERT ( SUCCEEDED(hr2) );
  898. hr = HRESULT_FROM_WIN32 ( dwWin32Error );
  899. goto Exit;
  900. }
  901. *plInstanceId = dwInstance;
  902. Exit:
  903. TraceFunctLeave ();
  904. return hr;
  905. }
  906. //$-------------------------------------------------------------------
  907. //
  908. // CNntpAdmin::DeleteInstance
  909. //
  910. // Description:
  911. //
  912. // Removes a virtual server from the metabase
  913. //
  914. // Parameters:
  915. //
  916. // pMetabase - The metabase object
  917. // lInstanceId - The ID of the virtual server to delete.
  918. // pErr - The resulting error code.
  919. //
  920. // Returns:
  921. //
  922. // Resulting error code in *pErr.
  923. //
  924. //--------------------------------------------------------------------
  925. HRESULT CNntpAdmin::DeleteInstance ( IMSAdminBase * pMetabase, long lInstanceId )
  926. {
  927. TraceFunctEnter ( "CNntpAdmin::CreateNewInstance" );
  928. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  929. HRESULT hr = NOERROR;
  930. CMetabaseKey mkeyNntp ( pMetabase );
  931. //
  932. // Tell U2 to delete any mappings associated with this virtual server:
  933. //
  934. ::DeleteMapping ( m_strServer, (BSTR) MD_SERVICE_NAME, lInstanceId );
  935. //
  936. // Delete the virtual server from the metabase:
  937. //
  938. hr = mkeyNntp.Open ( NNTP_MD_ROOT_PATH );
  939. if ( FAILED(hr) ) {
  940. ErrorTraceX ( (LPARAM) this, "Failed to open NntpSvc key, %x", GetLastError() );
  941. goto Exit;
  942. }
  943. hr = mkeyNntp.DestroyIntegerChild ( (DWORD) lInstanceId );
  944. if ( FAILED (hr) ) {
  945. goto Exit;
  946. }
  947. hr = mkeyNntp.Save ();
  948. BAIL_ON_FAILURE(hr);
  949. Exit:
  950. TraceFunctLeave ();
  951. return hr;
  952. }