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.

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