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.

1120 lines
24 KiB

  1. // admin.cpp : Implementation of CsmtpadmApp and DLL registration.
  2. #include "stdafx.h"
  3. #include "metautil.h"
  4. #include "smtpadm.h"
  5. #include "smtpcmn.h"
  6. #include "smtpprop.h"
  7. #include "admin.h"
  8. #include "version.h"
  9. #include "oleutil.h"
  10. #include "metakey.h"
  11. #define SMTP_DEF_SERVICE_VERSION ( 0 ) // MCIS
  12. // Must define THIS_FILE_* macros to use NntpCreateException()
  13. #define THIS_FILE_HELP_CONTEXT 0
  14. #define THIS_FILE_PROG_ID _T("Smtpadm.Admin.1")
  15. #define THIS_FILE_IID IID_ISmtpAdmin
  16. /////////////////////////////////////////////////////////////////////////////
  17. //
  18. CSmtpAdmin::CSmtpAdmin () :
  19. m_dwServiceInstance ( 0 )
  20. // CComBSTR's are initialized to NULL by default.
  21. {
  22. m_dwServiceVersion = SMTP_DEF_SERVICE_VERSION;
  23. }
  24. CSmtpAdmin::~CSmtpAdmin ()
  25. {
  26. // All CComBSTR's are freed automatically.
  27. }
  28. STDMETHODIMP CSmtpAdmin::InterfaceSupportsErrorInfo(REFIID riid)
  29. {
  30. static const IID* arr[] =
  31. {
  32. &IID_ISmtpAdmin,
  33. };
  34. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  35. {
  36. if (InlineIsEqualGUID(*arr[i],riid))
  37. return S_OK;
  38. }
  39. return S_FALSE;
  40. }
  41. STDMETHODIMP CSmtpAdmin::get_ServiceAdmin ( IDispatch ** ppIDispatch )
  42. {
  43. HRESULT hr = NOERROR;
  44. CComBSTR bstrT = _T("");
  45. CComPtr<ISmtpAdminService> pISmtpAdminService;
  46. if (!bstrT)
  47. {
  48. hr = E_OUTOFMEMORY;
  49. goto Error;
  50. }
  51. hr = StdPropertyHandoffIDispatch (
  52. CLSID_CSmtpAdminService,
  53. IID_ISmtpAdminService,
  54. &pISmtpAdminService,
  55. ppIDispatch
  56. );
  57. if ( FAILED(hr) ) {
  58. goto Error;
  59. }
  60. // Set default properties:
  61. hr = pISmtpAdminService->put_Server ( m_strServer ? m_strServer : bstrT );
  62. if ( FAILED (hr) ) {
  63. goto Error;
  64. }
  65. return hr;
  66. Error:
  67. SAFE_RELEASE ( *ppIDispatch );
  68. *ppIDispatch = NULL;
  69. return hr;
  70. // Destructor releases pISmtpAdminService
  71. }
  72. STDMETHODIMP CSmtpAdmin::get_VirtualServerAdmin ( IDispatch ** ppIDispatch )
  73. {
  74. HRESULT hr = NOERROR;
  75. CComBSTR bstrT = _T("");
  76. CComPtr<ISmtpAdminVirtualServer> pISmtpAdminVirtualServer;
  77. if (!bstrT)
  78. {
  79. hr = E_OUTOFMEMORY;
  80. goto Error;
  81. }
  82. hr = StdPropertyHandoffIDispatch (
  83. CLSID_CSmtpAdminVirtualServer,
  84. IID_ISmtpAdminVirtualServer,
  85. &pISmtpAdminVirtualServer,
  86. ppIDispatch
  87. );
  88. if ( FAILED(hr) ) {
  89. goto Error;
  90. }
  91. // Set default properties:
  92. hr = pISmtpAdminVirtualServer->put_Server ( m_strServer ? m_strServer : bstrT );
  93. if ( FAILED (hr) ) {
  94. goto Error;
  95. }
  96. hr = pISmtpAdminVirtualServer->put_ServiceInstance ( m_dwServiceInstance );
  97. if ( FAILED (hr) ) {
  98. goto Error;
  99. }
  100. return hr;
  101. Error:
  102. SAFE_RELEASE ( *ppIDispatch );
  103. *ppIDispatch = NULL;
  104. return hr;
  105. // Destructor releases pISmtpAdminVirtualServer
  106. }
  107. STDMETHODIMP CSmtpAdmin::get_SessionsAdmin ( IDispatch ** ppIDispatch )
  108. {
  109. HRESULT hr = NOERROR;
  110. CComBSTR bstrT = _T("");
  111. CComPtr<ISmtpAdminSessions> pISmtpAdminSessions;
  112. if (!bstrT)
  113. {
  114. hr = E_OUTOFMEMORY;
  115. goto Error;
  116. }
  117. hr = StdPropertyHandoffIDispatch (
  118. CLSID_CSmtpAdminSessions,
  119. IID_ISmtpAdminSessions,
  120. &pISmtpAdminSessions,
  121. ppIDispatch
  122. );
  123. if ( FAILED(hr) ) {
  124. goto Error;
  125. }
  126. // Set default properties:
  127. hr = pISmtpAdminSessions->put_Server ( m_strServer ? m_strServer : bstrT );
  128. if ( FAILED (hr) ) {
  129. goto Error;
  130. }
  131. hr = pISmtpAdminSessions->put_ServiceInstance ( m_dwServiceInstance );
  132. if ( FAILED (hr) ) {
  133. goto Error;
  134. }
  135. return hr;
  136. Error:
  137. SAFE_RELEASE ( *ppIDispatch );
  138. *ppIDispatch = NULL;
  139. return hr;
  140. // Destructor releases pISmtpAdminSessions
  141. }
  142. STDMETHODIMP CSmtpAdmin::get_AliasAdmin( IDispatch ** ppIDispatch )
  143. {
  144. HRESULT hr = NOERROR;
  145. CComBSTR bstrT = _T("");
  146. CComPtr<ISmtpAdminAlias> pISmtpAdminAlias;
  147. if (!bstrT)
  148. {
  149. hr = E_OUTOFMEMORY;
  150. goto Error;
  151. }
  152. hr = StdPropertyHandoffIDispatch (
  153. CLSID_CSmtpAdminAlias,
  154. IID_ISmtpAdminAlias,
  155. &pISmtpAdminAlias,
  156. ppIDispatch
  157. );
  158. if ( FAILED(hr) ) {
  159. goto Error;
  160. }
  161. // Set default properties:
  162. hr = pISmtpAdminAlias->put_Server ( m_strServer ? m_strServer : bstrT );
  163. if ( FAILED (hr) ) {
  164. goto Error;
  165. }
  166. hr = pISmtpAdminAlias->put_ServiceInstance ( m_dwServiceInstance );
  167. if ( FAILED (hr) ) {
  168. goto Error;
  169. }
  170. return hr;
  171. Error:
  172. SAFE_RELEASE ( *ppIDispatch );
  173. *ppIDispatch = NULL;
  174. return hr;
  175. // Destructor releases pISmtpAdminAlias
  176. }
  177. STDMETHODIMP CSmtpAdmin::get_UserAdmin( IDispatch ** ppIDispatch )
  178. {
  179. HRESULT hr = NOERROR;
  180. CComBSTR bstrT = _T("");
  181. CComPtr<ISmtpAdminUser> pISmtpAdminUser;
  182. if (!bstrT)
  183. {
  184. hr = E_OUTOFMEMORY;
  185. goto Error;
  186. }
  187. hr = StdPropertyHandoffIDispatch (
  188. CLSID_CSmtpAdminUser,
  189. IID_ISmtpAdminUser,
  190. &pISmtpAdminUser,
  191. ppIDispatch
  192. );
  193. if ( FAILED(hr) ) {
  194. goto Error;
  195. }
  196. // Set default properties:
  197. hr = pISmtpAdminUser->put_Server ( m_strServer ? m_strServer : bstrT );
  198. if ( FAILED (hr) ) {
  199. goto Error;
  200. }
  201. hr = pISmtpAdminUser->put_ServiceInstance ( m_dwServiceInstance );
  202. if ( FAILED (hr) ) {
  203. goto Error;
  204. }
  205. return hr;
  206. Error:
  207. SAFE_RELEASE ( *ppIDispatch );
  208. *ppIDispatch = NULL;
  209. return hr;
  210. // Destructor releases pISmtpAdminUser
  211. }
  212. STDMETHODIMP CSmtpAdmin::get_DLAdmin( IDispatch ** ppIDispatch )
  213. {
  214. HRESULT hr = NOERROR;
  215. CComBSTR bstrT = _T("");
  216. CComPtr<ISmtpAdminDL> pISmtpAdminDL;
  217. if (!bstrT)
  218. {
  219. hr = E_OUTOFMEMORY;
  220. goto Error;
  221. }
  222. hr = StdPropertyHandoffIDispatch (
  223. CLSID_CSmtpAdminDL,
  224. IID_ISmtpAdminDL,
  225. &pISmtpAdminDL,
  226. ppIDispatch
  227. );
  228. if ( FAILED(hr) ) {
  229. goto Error;
  230. }
  231. // Set default properties:
  232. hr = pISmtpAdminDL->put_Server ( m_strServer ? m_strServer : bstrT );
  233. if ( FAILED (hr) ) {
  234. goto Error;
  235. }
  236. hr = pISmtpAdminDL->put_ServiceInstance ( m_dwServiceInstance );
  237. if ( FAILED (hr) ) {
  238. goto Error;
  239. }
  240. return hr;
  241. Error:
  242. SAFE_RELEASE ( *ppIDispatch );
  243. *ppIDispatch = NULL;
  244. return hr;
  245. // Destructor releases pISmtpAdminDL
  246. }
  247. STDMETHODIMP CSmtpAdmin::get_DomainAdmin( IDispatch ** ppIDispatch )
  248. {
  249. HRESULT hr = NOERROR;
  250. CComBSTR bstrT = _T("");
  251. CComPtr<ISmtpAdminDomain> pISmtpAdminDomain;
  252. if (!bstrT)
  253. {
  254. hr = E_OUTOFMEMORY;
  255. goto Error;
  256. }
  257. hr = StdPropertyHandoffIDispatch (
  258. CLSID_CSmtpAdminDomain,
  259. IID_ISmtpAdminDomain,
  260. &pISmtpAdminDomain,
  261. ppIDispatch
  262. );
  263. if ( FAILED(hr) ) {
  264. goto Error;
  265. }
  266. // Set default properties:
  267. hr = pISmtpAdminDomain->put_Server ( m_strServer ? m_strServer : bstrT );
  268. if ( FAILED (hr) ) {
  269. goto Error;
  270. }
  271. hr = pISmtpAdminDomain->put_ServiceInstance ( m_dwServiceInstance );
  272. if ( FAILED (hr) ) {
  273. goto Error;
  274. }
  275. return hr;
  276. Error:
  277. SAFE_RELEASE ( *ppIDispatch );
  278. *ppIDispatch = NULL;
  279. return hr;
  280. // Destructor releases pISmtpAdminDomain
  281. }
  282. STDMETHODIMP CSmtpAdmin::get_VirtualDirectoryAdmin( IDispatch ** ppIDispatch )
  283. {
  284. HRESULT hr = NOERROR;
  285. CComBSTR bstrT = _T("");
  286. CComPtr<ISmtpAdminVirtualDirectory> pISmtpAdminVirtualDirectory;
  287. if (!bstrT)
  288. {
  289. hr = E_OUTOFMEMORY;
  290. goto Error;
  291. }
  292. hr = StdPropertyHandoffIDispatch (
  293. CLSID_CSmtpAdminVirtualDirectory,
  294. IID_ISmtpAdminVirtualDirectory,
  295. &pISmtpAdminVirtualDirectory,
  296. ppIDispatch
  297. );
  298. if ( FAILED(hr) ) {
  299. goto Error;
  300. }
  301. // Set default properties:
  302. hr = pISmtpAdminVirtualDirectory->put_Server ( m_strServer ? m_strServer : bstrT );
  303. if ( FAILED (hr) ) {
  304. goto Error;
  305. }
  306. hr = pISmtpAdminVirtualDirectory->put_ServiceInstance ( m_dwServiceInstance );
  307. if ( FAILED (hr) ) {
  308. goto Error;
  309. }
  310. return hr;
  311. Error:
  312. SAFE_RELEASE ( *ppIDispatch );
  313. *ppIDispatch = NULL;
  314. return hr;
  315. // Destructor releases pISmtpAdminVirtualDirectory
  316. }
  317. // Which service to configure:
  318. STDMETHODIMP CSmtpAdmin::get_Server ( BSTR * pstrServer )
  319. {
  320. return StdPropertyGet ( m_strServer, pstrServer );
  321. }
  322. STDMETHODIMP CSmtpAdmin::put_Server ( BSTR strServer )
  323. {
  324. return StdPropertyPutServerName ( &m_strServer, strServer );
  325. }
  326. STDMETHODIMP CSmtpAdmin::get_ServiceInstance ( long * plServiceInstance )
  327. {
  328. return StdPropertyGet ( m_dwServiceInstance, plServiceInstance );
  329. }
  330. STDMETHODIMP CSmtpAdmin::put_ServiceInstance ( long lServiceInstance )
  331. {
  332. return StdPropertyPut ( &m_dwServiceInstance, lServiceInstance );
  333. }
  334. // Versioning:
  335. STDMETHODIMP CSmtpAdmin::get_HighVersion ( long * plHighVersion )
  336. {
  337. *plHighVersion = HIGH_VERSION;
  338. return NOERROR;
  339. }
  340. STDMETHODIMP CSmtpAdmin::get_LowVersion ( long * plLowVersion )
  341. {
  342. *plLowVersion = LOW_VERSION;
  343. return NOERROR;
  344. }
  345. STDMETHODIMP CSmtpAdmin::get_BuildNum ( long * plBuildNumber )
  346. {
  347. *plBuildNumber = BUILD_NUM;
  348. return NOERROR;
  349. }
  350. STDMETHODIMP CSmtpAdmin::get_ServiceVersion ( long * plServiceVersion )
  351. {
  352. *plServiceVersion = m_dwServiceVersion;
  353. return NOERROR;
  354. }
  355. //////////////////////////////////////////////////////////////////////
  356. // Methods:
  357. //////////////////////////////////////////////////////////////////////
  358. //$-------------------------------------------------------------------
  359. //
  360. // CSmtpAdmin::EnumerateInstances
  361. //
  362. // Description:
  363. //
  364. // Returns a list of the virtual servers on the given machine.
  365. //
  366. // Parameters:
  367. //
  368. // ppsaInstances - Returned SAFEARRAY of instance IDs.
  369. // Must be freed by caller.
  370. //
  371. // Returns:
  372. //
  373. //
  374. //--------------------------------------------------------------------
  375. STDMETHODIMP CSmtpAdmin::EnumerateInstances ( SAFEARRAY ** ppsaInstances )
  376. {
  377. TraceFunctEnter ( "CSmtpAdmin::EnumerateInstances" );
  378. HRESULT hr = NOERROR;
  379. CComPtr<IMSAdminBase> pMetabase;
  380. SAFEARRAY * psaEmpty = NULL;
  381. SAFEARRAYBOUND sabound[1];
  382. // Check parameters:
  383. _ASSERT ( ppsaInstances != NULL );
  384. _ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
  385. if ( ppsaInstances == NULL ) {
  386. FatalTrace ( 0, "Bad return pointer" );
  387. hr = E_POINTER;
  388. goto Exit;
  389. }
  390. // Zero the out parameters:
  391. *ppsaInstances = NULL;
  392. // Set the return array to an empty array:
  393. sabound[0].lLbound = 0;
  394. sabound[0].cElements = 0;
  395. psaEmpty = SafeArrayCreate ( VT_I4, 1, sabound );
  396. if ( psaEmpty == NULL ) {
  397. FatalTrace ( (LPARAM) this, "Out of memory" );
  398. hr = E_OUTOFMEMORY;
  399. goto Exit;
  400. }
  401. *ppsaInstances = psaEmpty;
  402. // Get the metabase pointer:
  403. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  404. BAIL_ON_FAILURE(hr);
  405. // Enumerate the instances:
  406. hr = QueryMetabaseInstances ( pMetabase, ppsaInstances );
  407. Exit:
  408. if ( FAILED(hr) ) {
  409. _VERIFY ( SUCCEEDED (SafeArrayDestroy ( psaEmpty )) );
  410. if (ppsaInstances)
  411. *ppsaInstances = NULL;
  412. }
  413. TraceFunctLeave ();
  414. return hr;
  415. }
  416. STDMETHODIMP CSmtpAdmin::EnumerateInstancesVariant ( SAFEARRAY ** ppsaInstances )
  417. {
  418. TraceFunctEnter ( "CSmtpAdmin::EnumerateInstancesVariant" );
  419. HRESULT hr;
  420. SAFEARRAY * psaInstances = NULL;
  421. hr = EnumerateInstances ( &psaInstances );
  422. BAIL_ON_FAILURE(hr);
  423. hr = LongArrayToVariantArray ( psaInstances, ppsaInstances );
  424. BAIL_ON_FAILURE(hr);
  425. Exit:
  426. TraceFunctLeave ();
  427. return hr;
  428. }
  429. //$-------------------------------------------------------------------
  430. //
  431. // CSmtpAdmin::CreateInstance
  432. //
  433. // Description:
  434. //
  435. // Creates a new SMTP virtual server on the given machine.
  436. //
  437. // Parameters:
  438. //
  439. // plInstanceId - The new virtual server ID.
  440. //
  441. // Returns:
  442. //
  443. //
  444. //--------------------------------------------------------------------
  445. STDMETHODIMP CSmtpAdmin::CreateInstance ( BSTR pstrMailRoot, long * plInstanceId )
  446. {
  447. TraceFunctEnter ( "CSmtpAdmin::CreateInstance" );
  448. HRESULT hr = NOERROR;
  449. CComPtr<IMSAdminBase> pMetabase;
  450. // Check parameters:
  451. _ASSERT ( plInstanceId != NULL );
  452. _ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
  453. if ( plInstanceId == NULL ) {
  454. FatalTrace ( 0, "Bad return pointer" );
  455. hr = E_POINTER;
  456. goto Exit;
  457. }
  458. // Zero the out parameter:
  459. *plInstanceId = 0;
  460. // Get the metabase pointer:
  461. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  462. if ( FAILED(hr) ) {
  463. goto Exit;
  464. }
  465. // Create a new instance:
  466. hr = CreateNewInstance ( pMetabase, plInstanceId, pstrMailRoot );
  467. Exit:
  468. TraceFunctLeave ();
  469. return hr;
  470. }
  471. //$-------------------------------------------------------------------
  472. //
  473. // CSmtpAdmin::DestroyInstance
  474. //
  475. // Description:
  476. //
  477. // Removes the given virtual server.
  478. //
  479. // Parameters:
  480. //
  481. // lInstanceId - The ID of the virtual server to delete.
  482. //
  483. // Returns:
  484. //
  485. //
  486. //--------------------------------------------------------------------
  487. STDMETHODIMP CSmtpAdmin::DestroyInstance ( long lInstanceId )
  488. {
  489. TraceFunctEnter ( "CSmtpAdmin::DestroyInstance" );
  490. HRESULT hr = NOERROR;
  491. CComPtr<IMSAdminBase> pMetabase;
  492. // Get the metabase pointer:
  493. hr = m_mbFactory.GetMetabaseObject ( m_strServer, &pMetabase );
  494. if ( FAILED(hr) ) {
  495. goto Exit;
  496. }
  497. // Delete the instance:
  498. hr = DeleteInstance ( pMetabase, lInstanceId );
  499. Exit:
  500. TraceFunctLeave ();
  501. return hr;
  502. }
  503. //$-------------------------------------------------------------------
  504. //
  505. // CSmtpAdmin::ErrorToString
  506. //
  507. // Description:
  508. //
  509. // Translates an SMTP_ERROR_CODE to a readable string.
  510. //
  511. // Parameters:
  512. //
  513. // lErrorCode - Win32 error code.
  514. // pstrError - the readable error string.
  515. //
  516. // Returns:
  517. //
  518. // The error string in *pstrError.
  519. //
  520. //--------------------------------------------------------------------
  521. STDMETHODIMP CSmtpAdmin::ErrorToString ( DWORD lErrorCode, BSTR * pstrError )
  522. {
  523. TraceFunctEnter ( "CSmtpAdmin::ErrorToString" );
  524. _ASSERT ( IS_VALID_OUT_PARAM ( pstrError ) );
  525. HRESULT hr = NOERROR;
  526. DWORD dwFormatFlags;
  527. WCHAR wszError [ 1024 ];
  528. if ( pstrError == NULL ) {
  529. FatalTrace ( (LPARAM) this, "Bad return pointer" );
  530. TraceFunctLeave ();
  531. return E_POINTER;
  532. }
  533. //----------------------------------------------------------------
  534. //
  535. // Map error codes here:
  536. //
  537. //
  538. //----------------------------------------------------------------
  539. dwFormatFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
  540. if ( !FormatMessage ( dwFormatFlags, NULL, lErrorCode, 0, // Lang ID - Should be nonzero?
  541. wszError, 1024, NULL ) ) {
  542. // Didn't work, so put in a default message:
  543. WCHAR wszFormat [ 256 ];
  544. wszFormat[0] = L'\0';
  545. if ( !LoadStringW ( _Module.GetResourceInstance (), IDS_UNKNOWN_ERROR, wszFormat, 256 ) ||
  546. !*wszFormat ) {
  547. wcscpy ( wszFormat, L"Unknown Error (%1!d!)" );
  548. }
  549. FormatMessage (
  550. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  551. wszFormat,
  552. IDS_UNKNOWN_ERROR,
  553. 0,
  554. wszError,
  555. 1024,
  556. (va_list *) &lErrorCode
  557. );
  558. }
  559. //
  560. // We need to strip out any " from the string, because
  561. // Javascript will barf.
  562. //
  563. LPWSTR pch;
  564. for ( pch = wszError; *pch; pch++ ) {
  565. if ( *pch == L'\"' ) {
  566. *pch = L'\'';
  567. }
  568. }
  569. //
  570. // Strip off any trailing control characters.
  571. //
  572. for (pch = &wszError[wcslen(wszError) - 1];
  573. pch >= wszError && iswcntrl(*pch);
  574. pch --) {
  575. *pch = 0;
  576. }
  577. *pstrError = ::SysAllocString( wszError );
  578. if ( *pstrError == NULL ) {
  579. hr = E_OUTOFMEMORY;
  580. goto Exit;
  581. }
  582. Exit:
  583. TraceFunctLeave ();
  584. return hr;
  585. }
  586. //$-------------------------------------------------------------------
  587. //
  588. // CSmtpAdmin::Tokenize
  589. //
  590. // Description:
  591. //
  592. // Makes the given string safe for HTML & Javascript
  593. //
  594. // Parameters:
  595. //
  596. // strIn - the input string
  597. // strOut - the resulting string with appropriate escape sequences.
  598. //
  599. //--------------------------------------------------------------------
  600. STDMETHODIMP CSmtpAdmin::Tokenize ( BSTR strIn, BSTR * pstrOut )
  601. {
  602. TraceFunctEnter ( "CSmtpAdmin::Tokenize" );
  603. _ASSERT ( IS_VALID_STRING ( strIn ) );
  604. _ASSERT ( IS_VALID_OUT_PARAM ( pstrOut ) );
  605. HRESULT hr = NOERROR;
  606. PWCHAR pSrc = strIn;
  607. PWCHAR pSrcCur = NULL;
  608. PWCHAR pDstCur = NULL;
  609. PWCHAR pDst = NULL;
  610. *pstrOut = NULL;
  611. pDst = new WCHAR [ 3 * lstrlen ( strIn ) + 1 ];
  612. if ( pDst == NULL ) {
  613. FatalTrace ( (LPARAM) this, "Out of memory" );
  614. hr = E_OUTOFMEMORY;
  615. goto Exit;
  616. }
  617. for ( pSrcCur = pSrc, pDstCur = pDst; *pSrcCur; pSrcCur++ ) {
  618. switch ( *pSrcCur ) {
  619. case L'\\':
  620. *(pDstCur++) = L'%';
  621. *(pDstCur++) = L'5';
  622. *(pDstCur++) = L'c';
  623. break;
  624. case L' ':
  625. *(pDstCur++) = L'+';
  626. break;
  627. case L':':
  628. *(pDstCur++) = L'%';
  629. *(pDstCur++) = L'3';
  630. *(pDstCur++) = L'a';
  631. break;
  632. case L'/':
  633. *(pDstCur++) = L'%';
  634. *(pDstCur++) = L'2';
  635. *(pDstCur++) = L'f';
  636. break;
  637. default:
  638. *(pDstCur++) = *pSrcCur;
  639. }
  640. }
  641. *pDstCur = L'\0';
  642. *pstrOut = ::SysAllocString ( pDst );
  643. if ( *pstrOut == NULL ) {
  644. FatalTrace ( (LPARAM) this, "Out of memory" );
  645. hr = E_OUTOFMEMORY;
  646. goto Exit;
  647. }
  648. Exit:
  649. delete pDst;
  650. if ( FAILED(hr) && hr != DISP_E_EXCEPTION ) {
  651. hr = SmtpCreateExceptionFromHresult ( hr );
  652. }
  653. TraceFunctLeave ();
  654. return hr;
  655. }
  656. //$-------------------------------------------------------------------
  657. //
  658. // CSmtpAdmin::QueryMetabaseInstances
  659. //
  660. // Description:
  661. //
  662. // Retrieves the list of virtual servers from the metabase
  663. //
  664. // Parameters:
  665. //
  666. // pMetabase - the metabase object
  667. // ppsaInstances - resulting array of instance ids.
  668. //
  669. // Returns:
  670. //
  671. //
  672. //--------------------------------------------------------------------
  673. HRESULT CSmtpAdmin::QueryMetabaseInstances ( IMSAdminBase * pMetabase, SAFEARRAY ** ppsaInstances )
  674. {
  675. TraceFunctEnter ( "CSmtpAdmin::QueryMetabaseInstances" );
  676. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  677. _ASSERT ( IS_VALID_OUT_PARAM ( ppsaInstances ) );
  678. HRESULT hr = NOERROR;
  679. CMetabaseKey mkeySmtp ( pMetabase );
  680. SAFEARRAY * psaResult = NULL;
  681. DWORD cValidInstances = 0;
  682. SAFEARRAYBOUND rgsaBound[1];
  683. DWORD i;
  684. TCHAR szName[ METADATA_MAX_NAME_LEN ];
  685. long index[1];
  686. DWORD dwInstance;
  687. hr = mkeySmtp.Open ( SMTP_MD_ROOT_PATH );
  688. if ( FAILED(hr) ) {
  689. goto Exit;
  690. }
  691. // pickup the service version number:
  692. hr = mkeySmtp.GetDword ( _T(""), MD_SMTP_SERVICE_VERSION, &m_dwServiceVersion );
  693. if ( FAILED(hr) ) {
  694. m_dwServiceVersion = SMTP_DEF_SERVICE_VERSION;
  695. }
  696. hr = mkeySmtp.GetIntegerChildCount ( &cValidInstances );
  697. if ( FAILED(hr) ) {
  698. goto Exit;
  699. }
  700. // Allocate the array:
  701. rgsaBound[0].lLbound = 0;
  702. rgsaBound[0].cElements = cValidInstances;
  703. psaResult = SafeArrayCreate ( VT_I4, 1, rgsaBound );
  704. if ( psaResult == NULL ) {
  705. FatalTrace ( 0, "Out of memory" );
  706. hr = E_OUTOFMEMORY;
  707. goto Exit;
  708. }
  709. mkeySmtp.BeginChildEnumeration ();
  710. for ( i = 0; i < cValidInstances; i++ ) {
  711. hr = mkeySmtp.NextIntegerChild ( &dwInstance, szName );
  712. _ASSERT ( SUCCEEDED(hr) );
  713. index[0] = i;
  714. hr = SafeArrayPutElement ( psaResult, index, &dwInstance );
  715. _ASSERT ( SUCCEEDED(hr) );
  716. }
  717. *ppsaInstances = psaResult;
  718. _ASSERT ( SUCCEEDED(hr) );
  719. Exit:
  720. if ( FAILED (hr) ) {
  721. SafeArrayDestroy ( psaResult );
  722. }
  723. TraceFunctLeave ();
  724. return hr;
  725. }
  726. //$-------------------------------------------------------------------
  727. //
  728. // CSmtpAdmin::CreateNewInstance
  729. //
  730. // Description:
  731. //
  732. // Creates a new virtual server in the metabase.
  733. //
  734. // Parameters:
  735. //
  736. // pMetabase - The metabase object
  737. // plInstanceId - The new instance ID.
  738. //
  739. // Returns:
  740. //
  741. //
  742. //--------------------------------------------------------------------
  743. HRESULT CSmtpAdmin::CreateNewInstance (
  744. IMSAdminBase * pMetabase,
  745. long * plInstanceId,
  746. BSTR bstrMailRoot
  747. )
  748. {
  749. TraceFunctEnter ( "CSmtpAdmin::CreateNewInstance" );
  750. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  751. _ASSERT ( IS_VALID_OUT_PARAM ( plInstanceId ) );
  752. HRESULT hr = NOERROR;
  753. CMetabaseKey mkeySmtp ( pMetabase );
  754. DWORD dwInstance;
  755. TCHAR szInstance [ METADATA_MAX_NAME_LEN ];
  756. TCHAR szPath [ METADATA_MAX_NAME_LEN ];
  757. TCHAR szDir [512];
  758. DWORD cb;
  759. // Zero the out parameters:
  760. *plInstanceId = NULL;
  761. hr = mkeySmtp.Open ( SMTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
  762. if ( FAILED(hr) ) {
  763. ErrorTraceX ( (LPARAM) this, "Failed to open SmtpSvc key, %x", GetLastError() );
  764. goto Exit;
  765. }
  766. hr = mkeySmtp.CreateIntegerChild ( &dwInstance, szInstance );
  767. if ( FAILED (hr) ) {
  768. goto Exit;
  769. }
  770. wsprintf( szPath, _T("%s/Root"), szInstance );
  771. hr = mkeySmtp.CreateChild( szPath );
  772. if ( FAILED (hr) ) {
  773. goto Exit;
  774. }
  775. wsprintf( szPath, _T("%s/Root/MailRoot"), szInstance );
  776. hr = mkeySmtp.CreateChild( szPath );
  777. if ( FAILED (hr) ) {
  778. goto Exit;
  779. }
  780. // create mail root virtual directory
  781. if( bstrMailRoot && bstrMailRoot[0] )
  782. {
  783. // get rid of '\' at the end
  784. cb = lstrlen( bstrMailRoot );
  785. if( cb > 0 && bstrMailRoot[cb-1] == _T('\\') )
  786. bstrMailRoot[cb-1] = _T('\0');
  787. wsprintf( szPath, _T("%s/Root/MailRoot"), szInstance );
  788. cb = wsprintf( szDir, _T("%s\\Mailbox"), bstrMailRoot );
  789. mkeySmtp.SetString( szPath, MD_VR_PATH, szDir);
  790. // set badmail, drop, pickup, queue keys
  791. wsprintf( szPath, _T("%s"), szInstance );
  792. cb = wsprintf( szDir, _T("%s\\Badmail"), bstrMailRoot );
  793. mkeySmtp.SetString( szPath, MD_BAD_MAIL_DIR, szDir);
  794. // K2 only has drop doamin
  795. if( SERVICE_IS_K2(m_dwServiceVersion) )
  796. {
  797. cb = wsprintf( szDir, _T("%s\\Drop"), bstrMailRoot );
  798. mkeySmtp.SetString( szPath, MD_MAIL_DROP_DIR, szDir );
  799. }
  800. cb = wsprintf( szDir, _T("%s\\Pickup"), bstrMailRoot );
  801. mkeySmtp.SetString( szPath, MD_MAIL_PICKUP_DIR, szDir );
  802. cb = wsprintf( szDir, _T("%s\\Queue"), bstrMailRoot );
  803. mkeySmtp.SetString( szPath, MD_MAIL_QUEUE_DIR, szDir );
  804. // set the routing sources, it's MultiSZ
  805. cb = wsprintf( szDir, _T("szDataDirectory=%s\\Route"), bstrMailRoot );
  806. szDir[cb] = szDir[cb+1] = _T('\0');
  807. mkeySmtp.SetMultiSz( szPath, MD_ROUTING_SOURCES, szDir, (cb+2) * sizeof(TCHAR) );
  808. // MCIS needs SendNDRTo and SendBadTo as "Postmaster", setup should set it on service level
  809. if( SERVICE_IS_MCIS(m_dwServiceVersion) )
  810. {
  811. mkeySmtp.SetString( szPath, MD_SEND_NDR_TO, TSTR_POSTMASTR_NAME );
  812. mkeySmtp.SetString( szPath, MD_SEND_BAD_TO, TSTR_POSTMASTR_NAME );
  813. }
  814. }
  815. //
  816. // Initialize the server state:
  817. //
  818. mkeySmtp.SetDword ( szInstance, MD_SERVER_COMMAND, MD_SERVER_COMMAND_STOP );
  819. mkeySmtp.SetDword ( szInstance, MD_SERVER_STATE, MD_SERVER_STATE_STOPPED );
  820. mkeySmtp.SetDword ( szInstance, MD_SERVER_AUTOSTART, FALSE );
  821. // hr = mkeySmtp.Close();
  822. // BAIL_ON_FAILURE(hr);
  823. mkeySmtp.Close();
  824. hr = pMetabase->SaveData ( );
  825. if ( FAILED (hr) ) {
  826. goto Exit;
  827. }
  828. *plInstanceId = dwInstance;
  829. Exit:
  830. TraceFunctLeave ();
  831. return hr;
  832. }
  833. //$-------------------------------------------------------------------
  834. //
  835. // CSmtpAdmin::DeleteInstance
  836. //
  837. // Description:
  838. //
  839. // Removes a virtual server from the metabase
  840. //
  841. // Parameters:
  842. //
  843. // pMetabase - The metabase object
  844. // lInstanceId - The ID of the virtual server to delete.
  845. //
  846. // Returns:
  847. //
  848. //
  849. //--------------------------------------------------------------------
  850. HRESULT CSmtpAdmin::DeleteInstance ( IMSAdminBase * pMetabase, long lInstanceId )
  851. {
  852. TraceFunctEnter ( "CSmtpAdmin::CreateNewInstance" );
  853. _ASSERT ( IS_VALID_IN_PARAM ( pMetabase ) );
  854. HRESULT hr = NOERROR;
  855. CMetabaseKey mkeySmtp ( pMetabase );
  856. //
  857. // Tell U2 to delete any mappings associated with this virtual server:
  858. //
  859. ::DeleteMapping ( m_strServer, (BSTR) MD_SERVICE_NAME, lInstanceId );
  860. //
  861. // Delete the virtual server from the metabase:
  862. //
  863. hr = mkeySmtp.Open ( SMTP_MD_ROOT_PATH, METADATA_PERMISSION_WRITE );
  864. if ( FAILED(hr) ) {
  865. ErrorTraceX ( (LPARAM) this, "Failed to open SmtpSvc key, %x", GetLastError() );
  866. goto Exit;
  867. }
  868. hr = mkeySmtp.DestroyIntegerChild ( (DWORD) lInstanceId );
  869. if ( FAILED (hr) ) {
  870. goto Exit;
  871. }
  872. // hr = mkeySmtp.Close();
  873. // BAIL_ON_FAILURE(hr);
  874. mkeySmtp.Close();
  875. hr = pMetabase->SaveData ( );
  876. if ( FAILED (hr) ) {
  877. goto Exit;
  878. }
  879. Exit:
  880. TraceFunctLeave ();
  881. return hr;
  882. }