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.

1506 lines
34 KiB

  1. // MemberAccess.cpp : Implementation of CSsrMemberAccess
  2. #include "stdafx.h"
  3. #include "SSRTE.h"
  4. #include "SSRLog.h"
  5. #include "MemberAccess.h"
  6. #include "global.h"
  7. #include "util.h"
  8. static bool SsrPIsValidActionType ( DWORD dwType )
  9. {
  10. return ( (dwType & SSR_ACTION_PREPARE) ||
  11. (dwType & SSR_ACTION_APPLY)
  12. );
  13. }
  14. //
  15. // returning bool instead of bool is on purpose!
  16. //
  17. static bool SsrPIsDefaultAction ( DWORD dwType )
  18. {
  19. return ( (dwType & SSR_ACTION_PREPARE) ||
  20. (dwType & SSR_ACTION_APPLY)
  21. );
  22. }
  23. static bool SsrPIsSupportedRegValueType (DWORD dwType)
  24. {
  25. return (dwType == REG_SZ || dwType == REG_MULTI_SZ || dwType == REG_DWORD);
  26. }
  27. //---------------------------------------------------------------------
  28. // CSsrMemberAccess implementation
  29. //---------------------------------------------------------------------
  30. /*
  31. Routine Description:
  32. Name:
  33. CSsrMemberAccess::Cleanup
  34. Functionality:
  35. Cleanup the resource held by the object
  36. Virtual:
  37. No.
  38. Arguments:
  39. none.
  40. Return Value:
  41. none.
  42. Notes:
  43. */
  44. void CSsrMemberAccess::Cleanup()
  45. {
  46. MapMemberAD::iterator it = m_mapMemAD.begin();
  47. MapMemberAD::iterator itEnd = m_mapMemAD.end();
  48. while(it != itEnd)
  49. {
  50. CMemberAD * pVal = (*it).second;
  51. delete pVal;
  52. it++;
  53. }
  54. m_mapMemAD.clear();
  55. m_bstrName.Empty();
  56. m_bstrProgID.Empty();
  57. }
  58. /*
  59. Routine Description:
  60. Name:
  61. CSsrMemberAccess::GetSupportedActions
  62. Functionality:
  63. Get the names of the actions supported by this member
  64. Virtual:
  65. yes.
  66. Arguments:
  67. bDefault - If true, then this function queries the default actions
  68. pvarActionNames - The out parameter that receives the names of the actions of
  69. the given type supported by this member
  70. Return Value:
  71. Success: S_OK if there are actions of the type and the names are returned
  72. S_FALSE if there is no such actions supported by the member.
  73. Failure: various error codes.
  74. Notes:
  75. */
  76. STDMETHODIMP
  77. CSsrMemberAccess::GetSupportedActions (
  78. IN BOOL bDefault,
  79. OUT VARIANT * pvarActionNames //[out, retval]
  80. )
  81. {
  82. if (pvarActionNames == NULL)
  83. {
  84. return E_INVALIDARG;
  85. }
  86. //
  87. // now, create the array of action names
  88. //
  89. ::VariantInit(pvarActionNames);
  90. //
  91. // let's see how many actions of this type exists
  92. //
  93. MapMemberAD::iterator it = m_mapMemAD.begin();
  94. MapMemberAD::iterator itEnd = m_mapMemAD.end();
  95. int iCount = 0;
  96. //
  97. // we need to find out how many actions are of the given type
  98. //
  99. while(it != itEnd)
  100. {
  101. CMemberAD * pAD = (*it).second;
  102. _ASSERT(pAD != NULL);
  103. //
  104. // Be aware! Don't simply use bDefault == ::SsrPIsDefaultAction to test
  105. // because bDefault will be -1 when it comes from scripts!
  106. //
  107. if (bDefault && ::SsrPIsDefaultAction(pAD->GetType()) ||
  108. !bDefault && !::SsrPIsDefaultAction(pAD->GetType()))
  109. {
  110. ++iCount;
  111. }
  112. ++it;
  113. }
  114. if (iCount == 0)
  115. {
  116. return S_FALSE;
  117. }
  118. //
  119. // given the count we just get, now we know how big a safearray
  120. // we need to create.
  121. //
  122. SAFEARRAYBOUND rgsabound[1];
  123. rgsabound[0].lLbound = 0;
  124. rgsabound[0].cElements = iCount;
  125. SAFEARRAY * psa = ::SafeArrayCreate(VT_VARIANT , 1, rgsabound);
  126. HRESULT hr = S_OK;
  127. if (psa == NULL)
  128. {
  129. hr = E_OUTOFMEMORY;
  130. }
  131. else
  132. {
  133. //
  134. // we only add one name at a time
  135. //
  136. long indecies[1] = {0};
  137. it = m_mapMemAD.begin();
  138. while(it != itEnd)
  139. {
  140. CMemberAD * pAD = (*it).second;
  141. _ASSERT(pAD != NULL);
  142. //
  143. // count only those actions that match the requested action type
  144. //
  145. if (bDefault && ::SsrPIsDefaultAction(pAD->GetType()) ||
  146. !bDefault && !::SsrPIsDefaultAction(pAD->GetType()))
  147. {
  148. VARIANT v;
  149. v.vt = VT_BSTR;
  150. v.bstrVal = ::SysAllocString(pAD->GetActionName());
  151. if (v.bstrVal != NULL)
  152. {
  153. hr = ::SafeArrayPutElement(psa, indecies, &v);
  154. ::VariantClear(&v);
  155. }
  156. else
  157. {
  158. hr = E_OUTOFMEMORY;
  159. }
  160. if (FAILED(hr))
  161. {
  162. break;
  163. }
  164. indecies[0]++;
  165. }
  166. ++it;
  167. }
  168. //
  169. // only return the safearray if everything goes well
  170. //
  171. if (SUCCEEDED(hr))
  172. {
  173. pvarActionNames->vt = VT_ARRAY | VT_VARIANT;
  174. pvarActionNames->parray = psa;
  175. }
  176. else
  177. {
  178. ::SafeArrayDestroy(psa);
  179. }
  180. }
  181. return hr;
  182. }
  183. /*
  184. Routine Description:
  185. Name:
  186. CSsrMemberAccess::get_Name
  187. Functionality:
  188. Get the names of the member.
  189. Virtual:
  190. yes.
  191. Arguments:
  192. pbstrName - the BSTR which is the action of the member.
  193. Return Value:
  194. Success: S_OK as long as pbstrName is not NULL (which is invalid)
  195. Failure: various error codes.
  196. Notes:
  197. */
  198. STDMETHODIMP
  199. CSsrMemberAccess::get_Name (
  200. OUT BSTR * pbstrName // [out, retval]
  201. )
  202. {
  203. if (pbstrName == NULL)
  204. {
  205. return E_INVALIDARG;
  206. }
  207. *pbstrName = ::SysAllocString(m_bstrName);
  208. return (NULL == *pbstrName) ? E_OUTOFMEMORY : S_OK;
  209. }
  210. /*
  211. Routine Description:
  212. Name:
  213. CSsrMemberAccess::get_SsrMember
  214. Functionality:
  215. Return the SsrMember property - the custom ISsrMember object implemented by
  216. the member who desires to implement some custom behavior for certain actions.
  217. Virtual:
  218. yes.
  219. Arguments:
  220. pvarSsrMember - Out parameter receiving the custom ISsrMember object
  221. implemented by the member who desires to implement some
  222. custom behavior for certain actions.
  223. Return Value:
  224. Success: S_OK if this member does have a custom implementation
  225. of ISsrMember.
  226. S_FALSE if this member doesn't have a custom
  227. implementation of ISsrMember.
  228. Failure: various error codes
  229. Notes:
  230. */
  231. STDMETHODIMP
  232. CSsrMemberAccess::get_SsrMember (
  233. OUT VARIANT * pvarSsrMember //[out, retval]
  234. )
  235. {
  236. if (pvarSsrMember == NULL)
  237. {
  238. return E_INVALIDARG;
  239. }
  240. ::VariantInit(pvarSsrMember);
  241. HRESULT hr = S_FALSE;
  242. if (m_bstrProgID != NULL)
  243. {
  244. //
  245. // now create the COM object
  246. //
  247. GUID clsID;
  248. hr = ::CLSIDFromProgID(m_bstrProgID, &clsID);
  249. if (S_OK == hr)
  250. {
  251. ISsrMember * pISsrMember = NULL;
  252. hr = ::CoCreateInstance(clsID,
  253. NULL,
  254. CLSCTX_INPROC_SERVER,
  255. IID_ISsrMember,
  256. (LPVOID*)&pISsrMember
  257. );
  258. if (S_OK == hr)
  259. {
  260. pvarSsrMember->vt = VT_DISPATCH;
  261. pvarSsrMember->pdispVal = pISsrMember;
  262. }
  263. }
  264. }
  265. return hr;
  266. }
  267. /*
  268. Routine Description:
  269. Name:
  270. CSsrMemberAccess::Load
  271. Functionality:
  272. Will create this object based on the information available
  273. from the registry key.
  274. Virtual:
  275. no.
  276. Arguments:
  277. wszMemberFilePath - The path for the member registration XML file.
  278. Return Value:
  279. Success: S_OK if there are concrete member information being
  280. loaded (has action data).
  281. S_FALSE if there is really nothing this member has registered.
  282. Such a member should be discarded because it doesn't contain
  283. anything that SSR can use.
  284. Failure: various error codes.
  285. Notes:
  286. */
  287. HRESULT
  288. CSsrMemberAccess::Load (
  289. IN LPCWSTR wszMemberFilePath
  290. )
  291. {
  292. if (wszMemberFilePath == NULL || *wszMemberFilePath == L'\0')
  293. {
  294. return E_INVALIDARG;
  295. }
  296. //
  297. // just in case, this object is called to Load twice, clean up everything first
  298. //
  299. Cleanup();
  300. //
  301. // load the DOM
  302. //
  303. CComPtr<IXMLDOMDocument2> srpXmlDom;
  304. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument40,
  305. NULL,
  306. CLSCTX_SERVER,
  307. IID_IXMLDOMDocument2,
  308. (LPVOID*)(&srpXmlDom)
  309. );
  310. if (FAILED(hr))
  311. {
  312. return hr;
  313. }
  314. hr = SsrPLoadDOM(CComBSTR(wszMemberFilePath), SSR_LOADDOM_VALIDATE_ON_PARSE, srpXmlDom);
  315. if (FAILED(hr))
  316. {
  317. return hr;
  318. }
  319. CComPtr<IXMLDOMElement> srpXMLDocRoot;
  320. hr = srpXmlDom->get_documentElement(&srpXMLDocRoot);
  321. if (FAILED(hr))
  322. {
  323. return hr;
  324. }
  325. //
  326. // Get the UniqueName attribute
  327. //
  328. CComPtr<IXMLDOMNamedNodeMap> srpAttr;
  329. if (SUCCEEDED(hr))
  330. {
  331. CComVariant varAttr;
  332. hr = srpXMLDocRoot->getAttribute(g_bstrAttrUniqueName, &varAttr);
  333. if (FAILED(hr) || varAttr.vt != VT_BSTR)
  334. {
  335. //
  336. // we must have the unique name. This fails, we log and quit
  337. //
  338. return hr;
  339. }
  340. else
  341. {
  342. m_bstrName = varAttr.bstrVal;
  343. varAttr.vt = VT_EMPTY;
  344. }
  345. //
  346. // first, let's see if there is a ProgID value. We will ignore
  347. // any failure of reading the ProgID since it may not be there at all.
  348. //
  349. if (SUCCEEDED(srpXMLDocRoot->getAttribute(g_bstrAttrProgID, &varAttr)) &&
  350. varAttr.vt == VT_BSTR)
  351. {
  352. m_bstrProgID = varAttr.bstrVal;
  353. varAttr.vt = VT_EMPTY;
  354. }
  355. varAttr.Clear();
  356. //
  357. // Let's grab the major and minor versions. Currently, we don't have any
  358. // implementation to enforce them other than that the major version must
  359. // the same as our dll's. Otherwise we quit
  360. //
  361. if (SUCCEEDED(srpXMLDocRoot->getAttribute(g_bstrAttrMajorVersion, &varAttr)))
  362. {
  363. CComVariant varMajor;
  364. if (SUCCEEDED(VariantChangeType(&varMajor, &varAttr, VARIANT_NOVALUEPROP, VT_UI4)))
  365. {
  366. m_ulMajorVersion = varMajor.ulVal;
  367. }
  368. }
  369. if (m_ulMajorVersion != g_ulSsrEngineMajorVersion)
  370. {
  371. return E_SSR_MAJOR_VERSION_MISMATCH;
  372. }
  373. varAttr.Clear();
  374. if (SUCCEEDED(srpXMLDocRoot->getAttribute(g_bstrAttrMinorVersion, &varAttr)))
  375. {
  376. CComVariant varMinor;
  377. if (SUCCEEDED(VariantChangeType(&varMinor, &varAttr, VARIANT_NOVALUEPROP, VT_UI4)))
  378. {
  379. m_ulMinorVersion = varMinor.ulVal;
  380. }
  381. }
  382. }
  383. //
  384. // now, let's load each action
  385. //
  386. CComPtr<IXMLDOMNode> srpActionNode;
  387. hr = srpXMLDocRoot->get_firstChild(&srpActionNode);
  388. bool bLoaded = false;
  389. while (SUCCEEDED(hr) && srpActionNode != NULL)
  390. {
  391. CComBSTR bstrName;
  392. srpActionNode->get_nodeName(&bstrName);
  393. if (_wcsicmp(bstrName, g_bstrSupportedAction) == 0)
  394. {
  395. //
  396. // we only care about SupportedAction elements
  397. //
  398. CMemberAD * pMAD = NULL;
  399. hr = CMemberAD::LoadAD(m_bstrName, srpActionNode, m_bstrProgID, &pMAD);
  400. if (SUCCEEDED(hr))
  401. {
  402. //
  403. // we might load some empty procedure
  404. //
  405. if (pMAD != NULL)
  406. {
  407. const CActionType * pAT = pMAD->GetActionType();
  408. m_mapMemAD.insert(MapMemberAD::value_type(*pAT, pMAD));
  409. bLoaded = true;
  410. }
  411. }
  412. else
  413. {
  414. g_fblog.LogFeedback(SSR_FB_ERROR_LOAD_MEMBER | FBLog_Log,
  415. hr,
  416. wszMemberFilePath,
  417. IDS_XML_LOADING_MEMBER
  418. );
  419. break;
  420. }
  421. }
  422. CComPtr<IXMLDOMNode> srpNext;
  423. hr = srpActionNode->get_nextSibling(&srpNext);
  424. srpActionNode.Release();
  425. srpActionNode = srpNext;
  426. }
  427. if (FAILED(hr))
  428. {
  429. g_fblog.LogError(hr, L"CSsrMemberAccess::Load", wszMemberFilePath);
  430. }
  431. else if (bLoaded)
  432. {
  433. hr = S_OK;
  434. }
  435. return hr;
  436. }
  437. /*
  438. Routine Description:
  439. Name:
  440. CSsrMemberAccess::GetActionDataObject
  441. Functionality:
  442. Will find and return (if found) the CMemberAD that of the given name.
  443. This is a helper function
  444. Virtual:
  445. no.
  446. Arguments:
  447. lActionVerb - The action verb in long format.
  448. lActionType - The action type
  449. Return Value:
  450. If found, then the CMemberAD object pointer is return. It will return NULl
  451. if the given action is not registered or this operation can't be completed.
  452. Notes:
  453. */
  454. CMemberAD*
  455. CSsrMemberAccess::GetActionDataObject (
  456. IN SsrActionVerb lActionVerb,
  457. IN LONG lActionType
  458. )
  459. {
  460. CActionType at(lActionVerb, lActionType);
  461. MapMemberAD::iterator it = m_mapMemAD.find(at);
  462. MapMemberAD::iterator itEnd = m_mapMemAD.end();
  463. if (it != itEnd)
  464. {
  465. CMemberAD * pAD = (*it).second;
  466. return pAD;
  467. }
  468. return NULL;
  469. }
  470. /*
  471. Routine Description:
  472. Name:
  473. CSsrMemberAccess::MoveOutputFiles
  474. Functionality:
  475. Will move/delete all those output files.
  476. Virtual:
  477. no.
  478. Arguments:
  479. bstrActionVerb - the action verb
  480. pwszDirPathSrc - The directory path from which the files will be moved.
  481. pwszDirPathSrc - The directory path to which the files will be moved. This will
  482. be ignored if the action is a delete
  483. bDelete - Flag as whether the action is a move or delete.
  484. bLog - To prevent extraneous logging during restoring (backed up
  485. files), if this is not true, then no logging will occur
  486. Return Value:
  487. Success: S_OK
  488. Failure: various error codes
  489. Notes:
  490. */
  491. HRESULT
  492. CSsrMemberAccess::MoveOutputFiles (
  493. IN SsrActionVerb lActionVerb,
  494. IN LPCWSTR pwszDirPathSrc,
  495. IN LPCWSTR pwszDirPathDest,
  496. IN bool bDelete,
  497. IN bool bLog
  498. )
  499. {
  500. if (bLog)
  501. {
  502. CComBSTR bstrMsg(L"...");
  503. bstrMsg += m_bstrName;
  504. if (bstrMsg.m_str != NULL)
  505. {
  506. g_fblog.LogString(bstrMsg);
  507. }
  508. else
  509. {
  510. return E_OUTOFMEMORY;
  511. }
  512. }
  513. if (lActionVerb == ActionInvalid ||
  514. pwszDirPathSrc == NULL ||
  515. pwszDirPathDest == NULL && !bDelete )
  516. {
  517. return E_INVALIDARG;
  518. }
  519. //
  520. // output files are the transformation results. So, we need
  521. // the transformation result action data, which has the (xsl, output)
  522. // file pairs
  523. //
  524. //
  525. // find the action data for the given action
  526. //
  527. CActionType at(lActionVerb, SSR_ACTION_PREPARE);
  528. MapMemberAD::iterator it = m_mapMemAD.find(at);
  529. HRESULT hr = S_OK;
  530. //
  531. // since we will continue the cleanup in case of errors
  532. // we will return the last error
  533. //
  534. HRESULT hrLastError = S_OK;
  535. if (it != m_mapMemAD.end())
  536. {
  537. CMemberAD * pAD = (*it).second;
  538. _ASSERT(pAD != NULL);
  539. int iProcCount = pAD->GetProcedureCount();
  540. //
  541. // Each member (CMemberAD) may have multiple procedures for this action
  542. //
  543. for (int iProcIndex = 0; iProcIndex < iProcCount; iProcIndex++)
  544. {
  545. const CSsrProcedure * pProc = pAD->GetProcedure(iProcIndex);
  546. _ASSERT(pProc != NULL);
  547. int iFilePairsCount = pProc->GetFilePairCount();
  548. CSsrFilePair * pFilePair;
  549. //
  550. // each procedure may contain multiple file pairs
  551. //
  552. for (int iFPIndex = 0; iFPIndex < iFilePairsCount; iFPIndex++)
  553. {
  554. pFilePair = pProc->GetFilePair(iFPIndex);
  555. _ASSERT(pFilePair != NULL);
  556. //
  557. // if no second file (which is the result file) or the
  558. // second file is a static file, then don't bother to move them
  559. //
  560. if ( pFilePair->GetSecond() == NULL || pFilePair->IsStatic() )
  561. {
  562. continue;
  563. }
  564. //
  565. // move/delete this file
  566. //
  567. CComBSTR bstrSrcFullPath(pwszDirPathSrc);
  568. bstrSrcFullPath += L"\\";
  569. bstrSrcFullPath += pFilePair->GetSecond();
  570. if (bstrSrcFullPath.m_str == NULL)
  571. {
  572. return E_OUTOFMEMORY;
  573. }
  574. if (bDelete)
  575. {
  576. ::DeleteFile(bstrSrcFullPath);
  577. }
  578. else
  579. {
  580. CComBSTR bstrDestFullPath(pwszDirPathDest);
  581. bstrDestFullPath += L"\\";
  582. bstrDestFullPath += pFilePair->GetSecond();
  583. if (bstrDestFullPath.m_str == NULL)
  584. {
  585. return E_OUTOFMEMORY;
  586. }
  587. ::MoveFile(bstrSrcFullPath, bstrDestFullPath);
  588. }
  589. DWORD dwErrorCode = GetLastError();
  590. if (dwErrorCode != ERROR_SUCCESS &&
  591. dwErrorCode != ERROR_FILE_NOT_FOUND)
  592. {
  593. hr = HRESULT_FROM_WIN32(dwErrorCode);
  594. //
  595. // we will continue to delete the others. But log it
  596. //
  597. if (bLog)
  598. {
  599. hrLastError = hr;
  600. g_fblog.LogFeedback(SSR_FB_ERROR_FILE_DEL | FBLog_Log,
  601. hrLastError,
  602. bstrSrcFullPath,
  603. g_dwResNothing
  604. );
  605. }
  606. }
  607. }
  608. }
  609. }
  610. return hrLastError;
  611. }
  612. DWORD
  613. CSsrMemberAccess::GetActionCost (
  614. IN SsrActionVerb lActionVerb,
  615. IN LONG lActionType
  616. )const
  617. {
  618. CActionType at(lActionVerb, lActionType);
  619. MapMemberAD::iterator it = m_mapMemAD.find(at);
  620. DWORD dwSteps = 0;
  621. if (it != m_mapMemAD.end())
  622. {
  623. CMemberAD * pAD = (*it).second;
  624. _ASSERT(pAD != NULL);
  625. for (int i = 0; i < pAD->GetProcedureCount(); i++)
  626. {
  627. const CSsrProcedure * pProc = pAD->GetProcedure(i);
  628. if (pProc->IsDefaultProcedure())
  629. {
  630. //
  631. // each file pair will count as two steps
  632. //
  633. dwSteps += 2 * pProc->GetFilePairCount();
  634. }
  635. else
  636. {
  637. //
  638. // we have to consult with the custom member
  639. //
  640. CComPtr<ISsrMember> srpCusMember;
  641. GUID clsID;
  642. HRESULT hr = ::CLSIDFromProgID(pProc->GetProgID(), &clsID);
  643. if (S_OK == hr)
  644. {
  645. hr = ::CoCreateInstance(clsID,
  646. NULL,
  647. CLSCTX_INPROC_SERVER,
  648. IID_ISsrMember,
  649. (LPVOID*)&srpCusMember
  650. );
  651. }
  652. if (SUCCEEDED(hr))
  653. {
  654. LONG lCost = 0;
  655. hr = srpCusMember->get_ActionCost(SsrPGetActionVerbString(lActionVerb),
  656. lActionType,
  657. SSR_ACTION_COST_STEPS,
  658. &lCost
  659. );
  660. if (SUCCEEDED(hr))
  661. {
  662. dwSteps += lCost;
  663. }
  664. }
  665. }
  666. }
  667. }
  668. return dwSteps;
  669. }
  670. /*
  671. Routine Description:
  672. Name:
  673. CMemberAD::CMemberAD
  674. Functionality:
  675. Constructor.
  676. Virtual:
  677. no.
  678. Arguments:
  679. lActionVerb - The verb of the action.
  680. lActionType - The type of the action
  681. Return Value:
  682. None
  683. Notes:
  684. */
  685. CMemberAD::CMemberAD (
  686. IN SsrActionVerb lActionVerb,
  687. IN LONG lActionType
  688. ) : m_AT(lActionVerb, lActionType)
  689. {
  690. }
  691. /*
  692. Routine Description:
  693. Name:
  694. CMemberAD::~CMemberAD
  695. Functionality:
  696. destructor. This will clean up our map which contains BSTRs and VARIANTs,
  697. both of which are heap objects.
  698. Virtual:
  699. no.
  700. Arguments:
  701. None.
  702. Return Value:
  703. None
  704. Notes:
  705. */
  706. CMemberAD::~CMemberAD()
  707. {
  708. for (ULONG i = 0; i < m_vecProcedures.size(); i++)
  709. {
  710. delete m_vecProcedures[i];
  711. }
  712. m_vecProcedures.clear();
  713. }
  714. /*
  715. Routine Description:
  716. Name:
  717. CMemberAD::LoadAD
  718. Functionality:
  719. Will create an a action data object pertaining to a
  720. particular member and an action name.
  721. Virtual:
  722. no.
  723. Arguments:
  724. pActionNode - The SsrAction node
  725. ppMAD - The out parameter that receives the
  726. heap object created by this function
  727. Return Value:
  728. Success: S_OK if there are concrete action data loaded
  729. and in that case the out paramter ppMAD will
  730. point to the heap object. Otherwise, *ppMAD == NULL;
  731. Failure: various error codes.
  732. Notes:
  733. 2. Caller is responsible for releaseing the CMemberAD
  734. object passed back by the function.
  735. */
  736. HRESULT
  737. CMemberAD::LoadAD (
  738. IN LPCWSTR pwszMemberName,
  739. IN IXMLDOMNode * pActionNode,
  740. IN LPCWSTR pwszProgID,
  741. OUT CMemberAD ** ppMAD
  742. )
  743. {
  744. if (ppMAD == NULL)
  745. {
  746. return E_INVALIDARG;
  747. }
  748. *ppMAD = NULL;
  749. if (pActionNode == NULL)
  750. {
  751. return E_INVALIDARG;
  752. }
  753. CComPtr<IXMLDOMNamedNodeMap> srpAttr;
  754. HRESULT hr = pActionNode->get_attributes(&srpAttr);
  755. //
  756. // we must have attributes
  757. //
  758. if (FAILED(hr))
  759. {
  760. return hr;
  761. }
  762. CComBSTR bstrActionName, bstrActionType;
  763. LONG lActionType;
  764. //
  765. // ActionName and ActionType are mandatory attributes
  766. //
  767. hr = SsrPGetBSTRAttrValue(srpAttr, g_bstrAttrActionName, &bstrActionName);
  768. if (FAILED(hr))
  769. {
  770. return hr;
  771. }
  772. SsrActionVerb lActionVerb = SsrPGetActionVerbFromString(bstrActionName);
  773. if (lActionVerb == ActionInvalid)
  774. {
  775. return E_SSR_INVALID_ACTION_VERB;
  776. }
  777. hr = SsrPGetBSTRAttrValue(srpAttr, g_bstrAttrActionType, &bstrActionType);
  778. if (FAILED(hr))
  779. {
  780. return hr;
  781. }
  782. if (_wcsicmp(bstrActionType, g_pwszPrepare) == 0)
  783. {
  784. lActionType = SSR_ACTION_PREPARE;
  785. }
  786. else
  787. {
  788. _ASSERT(_wcsicmp(bstrActionType, g_pwszApply) == 0);
  789. lActionType = SSR_ACTION_APPLY;
  790. }
  791. *ppMAD = new CMemberAD(lActionVerb, lActionType);
  792. if (*ppMAD == NULL)
  793. {
  794. return E_OUTOFMEMORY;
  795. }
  796. //
  797. // now, we need to load the each individual procedure
  798. //
  799. bool bLoaded = false;
  800. if (SUCCEEDED(hr))
  801. {
  802. CComPtr<IXMLDOMNode> srpProcedure;
  803. hr = pActionNode->get_firstChild(&srpProcedure);
  804. while (SUCCEEDED(hr) && srpProcedure != NULL)
  805. {
  806. CComBSTR bstrName;
  807. srpProcedure->get_nodeName(&bstrName);
  808. bool bDefProc = _wcsicmp(bstrName, g_bstrDefaultProc) == 0;
  809. bool bCusProc = _wcsicmp(bstrName, g_bstrCustomProc) == 0;
  810. //
  811. // we only care about DefaultProc and CustomProc elements
  812. //
  813. if ( bDefProc || bCusProc )
  814. {
  815. CSsrProcedure * pNewProc = NULL;
  816. if (SUCCEEDED(hr))
  817. {
  818. hr = CSsrProcedure::StaticLoadProcedure(srpProcedure, bDefProc, pwszProgID, &pNewProc);
  819. }
  820. if (SUCCEEDED(hr))
  821. {
  822. //
  823. // give it to our vector
  824. //
  825. (*ppMAD)->m_vecProcedures.push_back(pNewProc);
  826. bLoaded = true;
  827. }
  828. else
  829. {
  830. //
  831. // will quit loading
  832. //
  833. g_fblog.LogFeedback(SSR_FB_ERROR_LOAD_MEMBER | FBLog_Log,
  834. hr,
  835. pwszMemberName,
  836. IDS_XML_LOADING_PROCEDURE
  837. );
  838. break;
  839. }
  840. }
  841. CComPtr<IXMLDOMNode> srpNext;
  842. hr = srpProcedure->get_nextSibling(&srpNext);
  843. srpProcedure.Release();
  844. srpProcedure = srpNext;
  845. }
  846. }
  847. //
  848. // either failed or loaded nothing
  849. //
  850. if (FAILED(hr) || !bLoaded)
  851. {
  852. delete *ppMAD;
  853. *ppMAD = NULL;
  854. }
  855. return SUCCEEDED(hr) ? S_OK : hr;
  856. }
  857. CSsrProcedure::CSsrProcedure()
  858. : m_bIsDefault(true)
  859. {
  860. }
  861. CSsrProcedure::~CSsrProcedure()
  862. {
  863. for (ULONG i = 0; i < m_vecFilePairs.size(); i++)
  864. {
  865. delete m_vecFilePairs[i];
  866. }
  867. m_vecFilePairs.clear();
  868. }
  869. HRESULT
  870. CSsrProcedure::StaticLoadProcedure (
  871. IN IXMLDOMNode * pNode,
  872. IN bool bDefProc,
  873. IN LPCWSTR pwszProgID,
  874. OUT CSsrProcedure ** ppNewProc
  875. )
  876. {
  877. if (ppNewProc == NULL)
  878. {
  879. return E_INVALIDARG;
  880. }
  881. *ppNewProc = NULL;
  882. if (pNode == NULL)
  883. {
  884. return E_INVALIDARG;
  885. }
  886. *ppNewProc = new CSsrProcedure;
  887. if (*ppNewProc == NULL)
  888. {
  889. return E_OUTOFMEMORY;
  890. }
  891. //
  892. // let's determine if this procedure is a default proc or custom proc.
  893. // That is determined by the tag name.
  894. //
  895. CComPtr<IXMLDOMNamedNodeMap> srpAttr;
  896. CComBSTR bstrTagName;
  897. HRESULT hr = S_OK;
  898. if (!bDefProc)
  899. {
  900. //
  901. // we are loding custom proc
  902. //
  903. (*ppNewProc)->m_bIsDefault = false;
  904. //
  905. // in this case, you should have no more than the ProgID that we care
  906. //
  907. hr = pNode->get_attributes(&srpAttr);
  908. _ASSERT(srpAttr);
  909. CComBSTR bstrProgID;
  910. if (SUCCEEDED(hr))
  911. {
  912. //
  913. // will try to get the ProgID attribute, may fail and we
  914. // don't care if it does
  915. //
  916. SsrPGetBSTRAttrValue(srpAttr, g_bstrAttrProgID, &bstrProgID);
  917. }
  918. if (bstrProgID != NULL)
  919. {
  920. (*ppNewProc)->m_bstrProgID = bstrProgID;
  921. }
  922. else
  923. {
  924. (*ppNewProc)->m_bstrProgID = pwszProgID;
  925. }
  926. }
  927. else
  928. {
  929. //
  930. // for default procedures, we should have a list of TransformFiles or ScriptFiles
  931. // elements. But we will create for both type of elements a CSsrFilePair object
  932. // and put it in the m_vecFilePairs vector
  933. //
  934. //
  935. // for that purpose, we need to traverse through the in sequential order
  936. // the TransformFiles and ScriptFiles elements
  937. //
  938. CComPtr<IXMLDOMNode> srpFilePairNode;
  939. CComPtr<IXMLDOMNode> srpNext;
  940. hr = pNode->get_firstChild(&srpFilePairNode);
  941. while (SUCCEEDED(hr) && srpFilePairNode != NULL)
  942. {
  943. //
  944. // Get the tag name. Empty the smart pointer so that we can re-use it
  945. //
  946. CComPtr<IXMLDOMNamedNodeMap> srpFilePairAttr;
  947. bstrTagName.Empty();
  948. hr = srpFilePairNode->get_nodeName(&bstrTagName);
  949. _ASSERT(SUCCEEDED(hr));
  950. if (FAILED(hr))
  951. {
  952. break;
  953. }
  954. hr = srpFilePairNode->get_attributes(&srpFilePairAttr);
  955. _ASSERT(srpAttr);
  956. //
  957. // we will ignore all other elements because we only know
  958. // two possible types of elements: TransformInfo and ScriptInfo
  959. //
  960. if (_wcsicmp(bstrTagName, g_bstrTransformInfo) == 0)
  961. {
  962. //
  963. // if it is a TransformFiles element, then, we really have a pair
  964. // (xsl, script)
  965. //
  966. //
  967. // we have potentially both TemplateFile and ResultFile attributes
  968. //
  969. CComBSTR bstrXsl, bstrResult;
  970. hr = SsrPGetBSTRAttrValue(srpFilePairAttr, g_bstrAttrTemplateFile, &bstrXsl);
  971. _ASSERT(SUCCEEDED(hr));
  972. //
  973. // may not have this one
  974. //
  975. SsrPGetBSTRAttrValue(srpFilePairAttr, g_bstrAttrResultFile, &bstrResult);
  976. if (SUCCEEDED(hr))
  977. {
  978. //
  979. // any result file is used as a result file (funny?), which means that the
  980. // file is created during the process of transformation
  981. //
  982. CSsrFilePair * pNewFilePair = new CSsrFilePair(bstrXsl, bstrResult);
  983. if (pNewFilePair != NULL)
  984. {
  985. (*ppNewProc)->m_vecFilePairs.push_back(pNewFilePair);
  986. }
  987. else
  988. {
  989. hr = E_OUTOFMEMORY;
  990. }
  991. }
  992. }
  993. else if (_wcsicmp(bstrTagName, g_bstrScriptInfo) == 0)
  994. {
  995. //
  996. // we will only have ScriptFile and usage attributes
  997. //
  998. CComBSTR bstrAttr;
  999. CComBSTR bstrScript;
  1000. hr = SsrPGetBSTRAttrValue(srpFilePairAttr, g_bstrAttrScriptFile, &bstrScript);
  1001. _ASSERT(SUCCEEDED(hr));
  1002. if (SUCCEEDED(hr))
  1003. {
  1004. //
  1005. // may not have this one, but in that case, it is defaulted
  1006. // to "Launch". Since an executable file will be launched,
  1007. // it's safer to assume that it is not an executable file.
  1008. // Likewise, since non-static file will be removed during
  1009. // preparation, we'd better assume that it is a static.
  1010. //
  1011. bool bIsExecutable = false;
  1012. bool bIsStatic = true;
  1013. //
  1014. // Get the IsExecutable attribute
  1015. //
  1016. bstrAttr.Empty();
  1017. if ( SUCCEEDED(SsrPGetBSTRAttrValue(srpFilePairAttr,
  1018. g_bstrAttrIsExecutable,
  1019. &bstrAttr)) &&
  1020. bstrAttr != NULL )
  1021. {
  1022. //
  1023. // err on the side of false is safer
  1024. //
  1025. if (_wcsicmp(bstrAttr, g_bstrTrue) != 0)
  1026. {
  1027. bIsExecutable = false;
  1028. }
  1029. else
  1030. {
  1031. bIsExecutable = true;
  1032. }
  1033. }
  1034. //
  1035. // Get the IsStatic attribute.
  1036. //
  1037. bstrAttr.Empty();
  1038. if ( SUCCEEDED(SsrPGetBSTRAttrValue(srpFilePairAttr,
  1039. g_bstrAttrIsStatic,
  1040. &bstrAttr)) &&
  1041. bstrAttr != NULL )
  1042. {
  1043. if (_wcsicmp(bstrAttr, g_bstrFalse) == 0)
  1044. {
  1045. bIsStatic = false;
  1046. }
  1047. }
  1048. //
  1049. // the script may be a result of a preparation, or a script file
  1050. // to launch during the action
  1051. //
  1052. CSsrFilePair * pNewFilePair = new CSsrFilePair(NULL, bstrScript, bIsStatic, bIsExecutable);
  1053. if (pNewFilePair != NULL)
  1054. {
  1055. (*ppNewProc)->m_vecFilePairs.push_back(pNewFilePair);
  1056. }
  1057. else
  1058. {
  1059. hr = E_OUTOFMEMORY;
  1060. }
  1061. }
  1062. }
  1063. if (FAILED(hr))
  1064. {
  1065. break;
  1066. }
  1067. //
  1068. // if it is a ScriptFiles element, then, it only has the script file
  1069. //
  1070. hr = srpFilePairNode->get_nextSibling(&srpNext);
  1071. srpFilePairNode = srpNext;
  1072. srpNext.Release();
  1073. }
  1074. }
  1075. if (FAILED(hr) && *ppNewProc != NULL)
  1076. {
  1077. delete *ppNewProc;
  1078. *ppNewProc = NULL;
  1079. }
  1080. return SUCCEEDED(hr) ? S_OK : hr;
  1081. }