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.

752 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: mmcprotocol.h
  8. //
  9. // Purpose: Creates a temporary pluggable internet protocol, mmc://
  10. //
  11. // History: 14-April-2000 Vivekj added
  12. //--------------------------------------------------------------------------
  13. #include<stdafx.h>
  14. #include<mmcprotocol.h>
  15. #include "tasks.h"
  16. #include "typeinfo.h" // for COleCacheCleanupObserver
  17. // {3C5F432A-EF40-4669-9974-9671D4FC2E12}
  18. static const CLSID CLSID_MMCProtocol = { 0x3c5f432a, 0xef40, 0x4669, { 0x99, 0x74, 0x96, 0x71, 0xd4, 0xfc, 0x2e, 0x12 } };
  19. static const WCHAR szMMC[] = _W(MMC_PROTOCOL_SCHEMA_NAME);
  20. static const WCHAR szMMCC[] = _W(MMC_PROTOCOL_SCHEMA_NAME) _W(":");
  21. static const WCHAR szPageBreak[] = _W(MMC_PAGEBREAK_RELATIVE_URL);
  22. static const WCHAR szMMCRES[] = L"%mmcres%";
  23. static const WCHAR chUNICODE = 0xfeff;
  24. #ifdef DBG
  25. CTraceTag tagProtocol(_T("MMC iNet Protocol"), _T("MMCProtocol"));
  26. #endif //DBG
  27. /***************************************************************************\
  28. *
  29. * FUNCTION: HasSchema
  30. *
  31. * PURPOSE: helper: determines if URL contains schema (like "something:" or "http:" )
  32. *
  33. * PARAMETERS:
  34. * LPCWSTR strURL
  35. *
  36. * RETURNS:
  37. * bool ; true == does contain schema
  38. *
  39. \***************************************************************************/
  40. inline bool HasSchema(LPCWSTR strURL)
  41. {
  42. if (strURL == NULL)
  43. return false;
  44. // skip spaces and schema name
  45. while ( iswspace(*strURL) || iswalnum(*strURL) )
  46. strURL++;
  47. // valid schema ends with ':'
  48. return *strURL == L':';
  49. }
  50. /***************************************************************************\
  51. *
  52. * FUNCTION: HasMMCSchema
  53. *
  54. * PURPOSE: helper: determines if URL contains mmc schema ( begins with "mmc:" )
  55. *
  56. * PARAMETERS:
  57. * LPCWSTR strURL
  58. *
  59. * RETURNS:
  60. * bool ; true == does contain mmc schema
  61. *
  62. \***************************************************************************/
  63. inline bool HasMMCSchema(LPCWSTR strURL)
  64. {
  65. if (strURL == NULL)
  66. return false;
  67. // skip spaces
  68. while ( iswspace(*strURL) )
  69. strURL++;
  70. return (0 == _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) );
  71. }
  72. /***************************************************************************\
  73. *
  74. * CLASS: CMMCProtocolRegistrar
  75. *
  76. * PURPOSE: register/ unregisters mmc protocol.
  77. * Also class provides cleanup functionality. Because it registers as
  78. * COleCacheCleanupObserver, it will receive the event when MMC
  79. * is about to uninitialize OLE, and will revoke registered mmc protocol
  80. *
  81. \***************************************************************************/
  82. class CMMCProtocolRegistrar : public COleCacheCleanupObserver
  83. {
  84. bool m_bRegistered;
  85. IClassFactoryPtr m_spClassFactory;
  86. public:
  87. // c-tor.
  88. CMMCProtocolRegistrar() : m_bRegistered(false) {}
  89. // registration / unregistration
  90. SC ScRegister();
  91. SC ScUnregister();
  92. // event sensor - unregisters mmc protocol
  93. virtual SC ScOnReleaseCachedOleObjects()
  94. {
  95. DECLARE_SC(sc, TEXT("ScOnReleaseCachedOleObjects"));
  96. return sc = ScUnregister();
  97. }
  98. };
  99. /***************************************************************************\
  100. *
  101. * METHOD: CMMCProtocolRegistrar::ScRegister
  102. *
  103. * PURPOSE: registers the protocol if required
  104. *
  105. * PARAMETERS:
  106. *
  107. * RETURNS:
  108. * SC - result code
  109. *
  110. \***************************************************************************/
  111. SC CMMCProtocolRegistrar::ScRegister()
  112. {
  113. DECLARE_SC(sc, TEXT("CMMCProtocolRegistrar::ScRegister"));
  114. // one time registration only
  115. if(m_bRegistered)
  116. return sc;
  117. // get internet session
  118. IInternetSessionPtr spInternetSession;
  119. sc = CoInternetGetSession(0, &spInternetSession, 0);
  120. if(sc)
  121. return sc;
  122. // doublecheck
  123. sc = ScCheckPointers(spInternetSession, E_FAIL);
  124. if(sc)
  125. return sc;
  126. // ask CComModule for the class factory
  127. sc = _Module.GetClassObject(CLSID_MMCProtocol, IID_IClassFactory, (void **)&m_spClassFactory);
  128. if(sc)
  129. return sc;
  130. // register the namespace
  131. sc = spInternetSession->RegisterNameSpace(m_spClassFactory, CLSID_MMCProtocol, szMMC, 0, NULL, 0);
  132. if(sc)
  133. return sc;
  134. // start observing cleanup requests - to unregister in time
  135. COleCacheCleanupManager::AddOleObserver(this);
  136. m_bRegistered = true; // did it.
  137. return sc;
  138. }
  139. /***************************************************************************\
  140. *
  141. * METHOD: CMMCProtocolRegistrar::ScUnregister
  142. *
  143. * PURPOSE: unregisters the protocol if one was registered
  144. *
  145. * PARAMETERS:
  146. *
  147. * RETURNS:
  148. * SC - result code
  149. *
  150. \***************************************************************************/
  151. SC CMMCProtocolRegistrar::ScUnregister()
  152. {
  153. DECLARE_SC(sc, TEXT("CMMCProtocolRegistrar::ScUnregister"));
  154. if (!m_bRegistered)
  155. return sc;
  156. // unregister
  157. IInternetSessionPtr spInternetSession;
  158. sc = CoInternetGetSession(0, &spInternetSession, 0);
  159. if(sc)
  160. {
  161. sc.Clear(); // no session - no headache
  162. }
  163. else // need to unregister
  164. {
  165. // recheck
  166. sc = ScCheckPointers(spInternetSession, E_UNEXPECTED);
  167. if(sc)
  168. return sc;
  169. // unregister the namespace
  170. sc = spInternetSession->UnregisterNameSpace(m_spClassFactory, szMMC);
  171. if(sc)
  172. return sc;
  173. }
  174. m_spClassFactory.Release();
  175. m_bRegistered = false;
  176. return sc;
  177. }
  178. /***************************************************************************\
  179. *
  180. * METHOD: CMMCProtocol::ScRegisterProtocol
  181. *
  182. * PURPOSE: Registers mmc protocol. IE will resove "mmc:..." ULRs to it
  183. *
  184. * PARAMETERS:
  185. *
  186. * RETURNS:
  187. * SC - result code
  188. *
  189. \***************************************************************************/
  190. SC
  191. CMMCProtocol::ScRegisterProtocol()
  192. {
  193. DECLARE_SC(sc, TEXT("CMMCProtocol::ScRegisterProtocol"));
  194. // registrar (unregisters on cleanup event) - needs to be static
  195. static CMMCProtocolRegistrar registrar;
  196. // let the registrar do the job
  197. return sc = registrar.ScRegister();
  198. }
  199. //*****************************************************************************
  200. // IInternetProtocolRoot interface
  201. //*****************************************************************************
  202. /***************************************************************************\
  203. *
  204. * METHOD: CMMCProtocol::Start
  205. *
  206. * PURPOSE: Starts data download thru this protocol
  207. *
  208. * PARAMETERS:
  209. * LPCWSTR szUrl
  210. * IInternetProtocolSink *pOIProtSink
  211. * IInternetBindInfo *pOIBindInfo
  212. * DWORD grfPI
  213. * HANDLE_PTR dwReserved
  214. *
  215. * RETURNS:
  216. * SC - result code
  217. *
  218. \***************************************************************************/
  219. STDMETHODIMP
  220. CMMCProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
  221. {
  222. DECLARE_SC(sc, TEXT("CMMCProtocol::Start"));
  223. // check inputs
  224. sc = ScCheckPointers(szUrl, pOIProtSink, pOIBindInfo);
  225. if(sc)
  226. return sc.ToHr();
  227. // reset position for reading
  228. m_uiReadOffs = 0;
  229. bool bPageBreakRequest = false;
  230. // see if it was a pagebreak requested
  231. sc = ScParsePageBreakURL( szUrl, bPageBreakRequest );
  232. if(sc)
  233. return sc.ToHr();
  234. if ( bPageBreakRequest )
  235. {
  236. // just report success (S_OK/S_FALSE) in case we were just parsing
  237. if ( grfPI & PI_PARSE_URL )
  238. return sc.ToHr();
  239. // construct a pagebreak
  240. m_strData = L"<HTML/>";
  241. sc = pOIProtSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
  242. if (sc)
  243. sc.TraceAndClear(); // ignore and continue
  244. }
  245. else
  246. {
  247. //if not a pagebreak - then taskpad
  248. GUID guidTaskpad = GUID_NULL;
  249. sc = ScParseTaskpadURL( szUrl, guidTaskpad );
  250. if(sc)
  251. return sc.ToHr();
  252. // report the S_FALSE instead of error in case we were just parsing
  253. if ( grfPI & PI_PARSE_URL )
  254. return ( sc.IsError() ? (sc = S_FALSE) : sc ).ToHr();
  255. if (sc)
  256. return sc.ToHr();
  257. // load the contents
  258. sc = ScGetTaskpadXML( guidTaskpad, m_strData );
  259. if (sc)
  260. return sc.ToHr();
  261. sc = pOIProtSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
  262. if (sc)
  263. sc.TraceAndClear(); // ignore and continue
  264. }
  265. const DWORD grfBSCF = BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE;
  266. const DWORD dwDataSize = m_strData.length() * sizeof (WCHAR);
  267. sc = pOIProtSink->ReportData(grfBSCF, dwDataSize , dwDataSize);
  268. if (sc)
  269. sc.TraceAndClear(); // ignore and continue
  270. sc = pOIProtSink->ReportResult(0, 0, 0);
  271. if (sc)
  272. sc.TraceAndClear(); // ignore and continue
  273. return sc.ToHr();
  274. }
  275. STDMETHODIMP CMMCProtocol::Continue(PROTOCOLDATA *pProtocolData) { return E_NOTIMPL; }
  276. STDMETHODIMP CMMCProtocol::Abort(HRESULT hrReason, DWORD dwOptions) { return S_OK; }
  277. STDMETHODIMP CMMCProtocol::Terminate(DWORD dwOptions) { return S_OK; }
  278. STDMETHODIMP CMMCProtocol::LockRequest(DWORD dwOptions) { return S_OK; }
  279. STDMETHODIMP CMMCProtocol::UnlockRequest() { return S_OK; }
  280. STDMETHODIMP CMMCProtocol::Suspend() { return E_NOTIMPL; }
  281. STDMETHODIMP CMMCProtocol::Resume() { return E_NOTIMPL; }
  282. STDMETHODIMP CMMCProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
  283. {
  284. return E_NOTIMPL;
  285. }
  286. //*****************************************************************************
  287. // IInternetProtocol interface
  288. //*****************************************************************************
  289. /***************************************************************************\
  290. *
  291. * METHOD: CMMCProtocol::Read
  292. *
  293. * PURPOSE: Reads data from the protocol
  294. *
  295. * PARAMETERS:
  296. * void *pv
  297. * ULONG cb
  298. * ULONG *pcbRead
  299. *
  300. * RETURNS:
  301. * SC - result code
  302. *
  303. \***************************************************************************/
  304. STDMETHODIMP CMMCProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
  305. {
  306. DECLARE_SC(sc, TEXT("CMMCProtocol::Read"));
  307. // parameter check;
  308. sc = ScCheckPointers(pv, pcbRead);
  309. if(sc)
  310. return sc.ToHr();
  311. // init out parameter;
  312. *pcbRead = 0;
  313. size_t size = ( m_strData.length() ) * sizeof(WCHAR);
  314. if ( size <= m_uiReadOffs )
  315. return (sc = S_FALSE).ToHr(); // no more data
  316. // calculate the size we'll return
  317. *pcbRead = size - m_uiReadOffs;
  318. if (size - m_uiReadOffs > cb)
  319. *pcbRead = cb;
  320. if (*pcbRead)
  321. memcpy( pv, reinterpret_cast<const BYTE*>( m_strData.begin() ) + m_uiReadOffs, *pcbRead );
  322. m_uiReadOffs += *pcbRead;
  323. if ( size <= m_uiReadOffs )
  324. return (sc = S_FALSE).ToHr(); // no more data
  325. return sc.ToHr();
  326. }
  327. //*****************************************************************************
  328. // IInternetProtocolInfo interface
  329. //*****************************************************************************
  330. STDMETHODIMP
  331. CMMCProtocol::ParseUrl( LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
  332. {
  333. DECLARE_SC(sc, TEXT("CMMCProtocol::ParseUrl"));
  334. if (ParseAction == PARSE_SECURITY_URL)
  335. {
  336. // get system directory (like "c:\winnt\system32\")
  337. std::wstring windir;
  338. AppendMMCPath(windir);
  339. windir += L'\\';
  340. // we are as secure as windir is - report the url (like "c:\winnt\system32\")
  341. *pcchResult = windir.length() + 1;
  342. // check if we have enough place for the result and terminating zero
  343. if ( cchResult <= windir.length() )
  344. return S_FALSE; // not enough
  345. wcscpy(pwzResult, windir.c_str());
  346. return (sc = S_OK).ToHr();
  347. }
  348. return INET_E_DEFAULT_ACTION;
  349. }
  350. /***************************************************************************\
  351. *
  352. * METHOD: CMMCProtocol::CombineUrl
  353. *
  354. * PURPOSE: combines base + relative url to resulting url
  355. * we do local variable substitution here
  356. *
  357. * PARAMETERS:
  358. * LPCWSTR pwzBaseUrl
  359. * LPCWSTR pwzRelativeUrl
  360. * DWORD dwCombineFlags
  361. * LPWSTR pwzResult
  362. * DWORD cchResult
  363. * DWORD *pcchResult
  364. * DWORD dwReserved
  365. *
  366. * RETURNS:
  367. * SC - result code
  368. *
  369. \***************************************************************************/
  370. STDMETHODIMP CMMCProtocol::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
  371. {
  372. DECLARE_SC(sc, TEXT("CMMCProtocol::CombineUrl"));
  373. #ifdef DBG
  374. USES_CONVERSION;
  375. Trace(tagProtocol, _T("CombineUrl: [%s] + [%s]"), W2CT(pwzBaseUrl), W2CT(pwzRelativeUrl));
  376. #endif //DBG
  377. std::wstring temp1;
  378. if (HasMMCSchema(pwzBaseUrl))
  379. {
  380. // our stuff
  381. temp1 = pwzRelativeUrl;
  382. ExpandMMCVars(temp1);
  383. if ( ! HasSchema( temp1.c_str() ) )
  384. {
  385. // combine everything into relative URL
  386. temp1.insert( 0, pwzBaseUrl );
  387. }
  388. // form 'new' relative address
  389. pwzRelativeUrl = temp1.c_str();
  390. // say we are refered from http - let it do the dirty job ;)
  391. pwzBaseUrl = L"http://";
  392. }
  393. // since we stripped out ourselfs from pwzBaseUrl - it will not recurse back,
  394. // but will do original html stuff
  395. sc = CoInternetCombineUrl( pwzBaseUrl, pwzRelativeUrl, dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved );
  396. if (sc)
  397. return sc.ToHr();
  398. Trace(tagProtocol, _T("CombineUrl: == [%s]"), W2CT(pwzResult));
  399. return sc.ToHr();
  400. }
  401. /***************************************************************************\
  402. *
  403. * METHOD: CMMCProtocol::CompareUrl
  404. *
  405. * PURPOSE: compares URLs if they are the same
  406. *
  407. * PARAMETERS:
  408. * LPCWSTR pwzUrl1
  409. * LPCWSTR pwzUrl2
  410. * DWORD dwCompareFlags
  411. *
  412. * RETURNS:
  413. * SC - result code
  414. *
  415. \***************************************************************************/
  416. STDMETHODIMP CMMCProtocol::CompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2,DWORD dwCompareFlags)
  417. {
  418. DECLARE_SC(sc, TEXT("CMMCProtocol::CompareUrl"));
  419. return INET_E_DEFAULT_ACTION;
  420. }
  421. /***************************************************************************\
  422. *
  423. * METHOD: CMMCProtocol::QueryInfo
  424. *
  425. * PURPOSE: Queries info about URL
  426. *
  427. * PARAMETERS:
  428. * LPCWSTR pwzUrl
  429. * QUERYOPTION QueryOption
  430. * DWORD dwQueryFlags
  431. * LPVOID pBuffer
  432. * DWORD cbBuffer
  433. * DWORD *pcbBuf
  434. * DWORD dwReserved
  435. *
  436. * RETURNS:
  437. * SC - result code
  438. *
  439. \***************************************************************************/
  440. STDMETHODIMP CMMCProtocol::QueryInfo( LPCWSTR pwzUrl, QUERYOPTION QueryOption,DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
  441. {
  442. DECLARE_SC(sc, TEXT("CMMCProtocol::QueryInfo"));
  443. if (QueryOption == QUERY_USES_NETWORK)
  444. {
  445. if (cbBuffer >= 4)
  446. {
  447. *(LPDWORD)pBuffer = FALSE; // does not use the network
  448. *pcbBuf = 4;
  449. return S_OK;
  450. }
  451. }
  452. else if (QueryOption == QUERY_IS_SAFE)
  453. {
  454. if (cbBuffer >= 4)
  455. {
  456. *(LPDWORD)pBuffer = TRUE; // only serves trusted content
  457. *pcbBuf = 4;
  458. return S_OK;
  459. }
  460. }
  461. return INET_E_DEFAULT_ACTION;
  462. }
  463. /***************************************************************************\
  464. *
  465. * METHOD: CMMCProtocol::ScParseTaskpadURL
  466. *
  467. * PURPOSE: Extracts taskpad guid from URL given to the protocol
  468. *
  469. * PARAMETERS:
  470. * LPCWSTR strURL [in] - URL
  471. * GUID& guid [out] - extracted guid
  472. *
  473. * RETURNS:
  474. * SC - result code
  475. *
  476. \***************************************************************************/
  477. SC CMMCProtocol::ScParseTaskpadURL( LPCWSTR strURL, GUID& guid )
  478. {
  479. DECLARE_SC(sc, TEXT("CMMCProtocol::ScParseTaskpadURL"));
  480. guid = GUID_NULL;
  481. sc = ScCheckPointers(strURL);
  482. if (sc)
  483. return sc;
  484. // taskpad url should be in form "mmc:{guid}"
  485. // check for "mmc:"
  486. if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
  487. return sc = E_FAIL;
  488. // skip "mmc:"
  489. strURL += wcslen(szMMCC);
  490. // get the url
  491. sc = CLSIDFromString( const_cast<LPWSTR>(strURL), &guid );
  492. if (sc)
  493. return sc;
  494. return sc;
  495. }
  496. /***************************************************************************\
  497. *
  498. * METHOD: CMMCProtocol::ScParsePageBreakURL
  499. *
  500. * PURPOSE: Checks if URL given to the protocol is a request for a pagebreak
  501. *
  502. * PARAMETERS:
  503. * LPCWSTR strURL [in] - URL
  504. * bool& bPageBreak [out] - true it it is a request for pagebreak
  505. *
  506. * RETURNS:
  507. * SC - result code
  508. *
  509. \***************************************************************************/
  510. SC CMMCProtocol::ScParsePageBreakURL( LPCWSTR strURL, bool& bPageBreak )
  511. {
  512. DECLARE_SC(sc, TEXT("CMMCProtocol::ScParsePageBreakURL"));
  513. bPageBreak = false;
  514. sc = ScCheckPointers(strURL);
  515. if (sc)
  516. return sc;
  517. // pagebreak url should be in form "mmc:pagebreak.<number>"
  518. // check for "mmc:"
  519. if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
  520. return sc; // not an error - return value updated
  521. // skip "mmc:"
  522. strURL += wcslen(szMMCC);
  523. // get the url
  524. bPageBreak = ( 0 == wcsncmp( strURL, szPageBreak, wcslen(szPageBreak) ) );
  525. return sc;
  526. }
  527. /***************************************************************************\
  528. *
  529. * METHOD: CMMCProtocol::ScGetTaskpadXML
  530. *
  531. * PURPOSE: given the guid uploads taskpad XML string to the string
  532. *
  533. * PARAMETERS:
  534. * const GUID& guid [in] - taskpad guid
  535. * std::wstring& strResultData [out] - taskpad xml string
  536. *
  537. * RETURNS:
  538. * SC - result code
  539. *
  540. \***************************************************************************/
  541. SC CMMCProtocol::ScGetTaskpadXML( const GUID& guid, std::wstring& strResultData )
  542. {
  543. DECLARE_SC(sc, TEXT("CMMCProtocol::ScGetTaskpadXML"));
  544. strResultData.erase();
  545. CScopeTree* pScopeTree = CScopeTree::GetScopeTree();
  546. sc = ScCheckPointers(pScopeTree, E_FAIL);
  547. if(sc)
  548. return sc.ToHr();
  549. CConsoleTaskpadList * pConsoleTaskpadList = pScopeTree->GetConsoleTaskpadList();
  550. sc = ScCheckPointers(pConsoleTaskpadList, E_FAIL);
  551. if(sc)
  552. return sc.ToHr();
  553. for(CConsoleTaskpadList::iterator iter = pConsoleTaskpadList->begin(); iter!= pConsoleTaskpadList->end(); ++iter)
  554. {
  555. CConsoleTaskpad &consoleTaskpad = *iter;
  556. // check if this is the one we are looking for
  557. if ( !IsEqualGUID( guid, consoleTaskpad.GetID() ) )
  558. continue;
  559. // convert the taskpad to a string
  560. CStr strTaskpadHTML;
  561. sc = consoleTaskpad.ScGetHTML(strTaskpadHTML); // create a string version of the taskpad
  562. if(sc)
  563. return sc.ToHr();
  564. // form the result string
  565. USES_CONVERSION;
  566. strResultData = chUNICODE;
  567. strResultData += T2CW(strTaskpadHTML);
  568. return sc;
  569. }
  570. // not found
  571. return sc = E_FAIL;
  572. }
  573. /***************************************************************************\
  574. *
  575. * METHOD: CMMCProtocol::AppendMMCPath
  576. *
  577. * PURPOSE: helper. Appends the mmcndmgr.dll dir (no file name) to the string
  578. * It may append something like: "c:\winnt\system32"
  579. *
  580. * PARAMETERS:
  581. * std::wstring& str [in/out] - string to edit
  582. *
  583. * RETURNS:
  584. * SC - result code
  585. *
  586. \***************************************************************************/
  587. void CMMCProtocol::AppendMMCPath(std::wstring& str)
  588. {
  589. TCHAR szModule[_MAX_PATH+10] = { 0 };
  590. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  591. USES_CONVERSION;
  592. LPCWSTR strModule = T2CW(szModule);
  593. LPCWSTR dirEnd = wcsrchr( strModule, L'\\' );
  594. if (dirEnd != NULL)
  595. str.append(strModule, dirEnd);
  596. }
  597. /***************************************************************************\
  598. *
  599. * METHOD: CMMCProtocol::ExpandMMCVars
  600. *
  601. * PURPOSE: helper. expands any %mmcres% contained in the string
  602. * It expands it to something like "res://c:\winnt\system32\mmcndmgr.dll"
  603. *
  604. * PARAMETERS:
  605. * std::wstring& str [in/out] - string to edit
  606. *
  607. * RETURNS:
  608. * SC - result code
  609. *
  610. \***************************************************************************/
  611. void CMMCProtocol::ExpandMMCVars(std::wstring& str)
  612. {
  613. // first - form the values
  614. TCHAR szModule[_MAX_PATH+10] = { 0 };
  615. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  616. USES_CONVERSION;
  617. LPCWSTR strModule = T2CW(szModule);
  618. std::wstring mmcres = L"res://";
  619. mmcres += strModule;
  620. // second - replace the instances
  621. int pos;
  622. while (std::wstring::npos != (pos = str.find(szMMCRES) ) )
  623. {
  624. // make one substitution
  625. str.replace( pos, wcslen(szMMCRES), mmcres) ;
  626. }
  627. }