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.

766 lines
22 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. sc = StringCchCopyW(pwzResult,cchResult, windir.c_str());
  346. if(sc)
  347. return sc.ToHr();
  348. return (sc = S_OK).ToHr();
  349. }
  350. return INET_E_DEFAULT_ACTION;
  351. }
  352. /***************************************************************************\
  353. *
  354. * METHOD: CMMCProtocol::CombineUrl
  355. *
  356. * PURPOSE: combines base + relative url to resulting url
  357. * we do local variable substitution here
  358. *
  359. * PARAMETERS:
  360. * LPCWSTR pwzBaseUrl
  361. * LPCWSTR pwzRelativeUrl
  362. * DWORD dwCombineFlags
  363. * LPWSTR pwzResult
  364. * DWORD cchResult
  365. * DWORD *pcchResult
  366. * DWORD dwReserved
  367. *
  368. * RETURNS:
  369. * SC - result code
  370. *
  371. \***************************************************************************/
  372. STDMETHODIMP CMMCProtocol::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
  373. {
  374. DECLARE_SC(sc, TEXT("CMMCProtocol::CombineUrl"));
  375. #ifdef DBG
  376. USES_CONVERSION;
  377. Trace(tagProtocol, _T("CombineUrl: [%s] + [%s]"), W2CT(pwzBaseUrl), W2CT(pwzRelativeUrl));
  378. #endif //DBG
  379. std::wstring temp1;
  380. if (HasMMCSchema(pwzBaseUrl))
  381. {
  382. // our stuff
  383. temp1 = pwzRelativeUrl;
  384. ExpandMMCVars(temp1);
  385. if ( ! HasSchema( temp1.c_str() ) )
  386. {
  387. // combine everything into relative URL
  388. temp1.insert( 0, pwzBaseUrl );
  389. }
  390. // form 'new' relative address
  391. pwzRelativeUrl = temp1.c_str();
  392. // say we are refered from http - let it do the dirty job ;)
  393. pwzBaseUrl = L"http://";
  394. }
  395. // since we stripped out ourselfs from pwzBaseUrl - it will not recurse back,
  396. // but will do original html stuff
  397. sc = CoInternetCombineUrl( pwzBaseUrl, pwzRelativeUrl, dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved );
  398. if (sc)
  399. return sc.ToHr();
  400. Trace(tagProtocol, _T("CombineUrl: == [%s]"), W2CT(pwzResult));
  401. return sc.ToHr();
  402. }
  403. /***************************************************************************\
  404. *
  405. * METHOD: CMMCProtocol::CompareUrl
  406. *
  407. * PURPOSE: compares URLs if they are the same
  408. *
  409. * PARAMETERS:
  410. * LPCWSTR pwzUrl1
  411. * LPCWSTR pwzUrl2
  412. * DWORD dwCompareFlags
  413. *
  414. * RETURNS:
  415. * SC - result code
  416. *
  417. \***************************************************************************/
  418. STDMETHODIMP CMMCProtocol::CompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2,DWORD dwCompareFlags)
  419. {
  420. DECLARE_SC(sc, TEXT("CMMCProtocol::CompareUrl"));
  421. return INET_E_DEFAULT_ACTION;
  422. }
  423. /***************************************************************************\
  424. *
  425. * METHOD: CMMCProtocol::QueryInfo
  426. *
  427. * PURPOSE: Queries info about URL
  428. *
  429. * PARAMETERS:
  430. * LPCWSTR pwzUrl
  431. * QUERYOPTION QueryOption
  432. * DWORD dwQueryFlags
  433. * LPVOID pBuffer
  434. * DWORD cbBuffer
  435. * DWORD *pcbBuf
  436. * DWORD dwReserved
  437. *
  438. * RETURNS:
  439. * SC - result code
  440. *
  441. \***************************************************************************/
  442. STDMETHODIMP CMMCProtocol::QueryInfo( LPCWSTR pwzUrl, QUERYOPTION QueryOption,DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
  443. {
  444. DECLARE_SC(sc, TEXT("CMMCProtocol::QueryInfo"));
  445. if (QueryOption == QUERY_USES_NETWORK)
  446. {
  447. if (cbBuffer >= 4)
  448. {
  449. *(LPDWORD)pBuffer = FALSE; // does not use the network
  450. *pcbBuf = 4;
  451. return S_OK;
  452. }
  453. }
  454. else if (QueryOption == QUERY_IS_SAFE)
  455. {
  456. if (cbBuffer >= 4)
  457. {
  458. *(LPDWORD)pBuffer = TRUE; // only serves trusted content
  459. *pcbBuf = 4;
  460. return S_OK;
  461. }
  462. }
  463. return INET_E_DEFAULT_ACTION;
  464. }
  465. /***************************************************************************\
  466. *
  467. * METHOD: CMMCProtocol::ScParseTaskpadURL
  468. *
  469. * PURPOSE: Extracts taskpad guid from URL given to the protocol
  470. *
  471. * PARAMETERS:
  472. * LPCWSTR strURL [in] - URL
  473. * GUID& guid [out] - extracted guid
  474. *
  475. * RETURNS:
  476. * SC - result code
  477. *
  478. \***************************************************************************/
  479. SC CMMCProtocol::ScParseTaskpadURL( LPCWSTR strURL, GUID& guid )
  480. {
  481. DECLARE_SC(sc, TEXT("CMMCProtocol::ScParseTaskpadURL"));
  482. guid = GUID_NULL;
  483. sc = ScCheckPointers(strURL);
  484. if (sc)
  485. return sc;
  486. // taskpad url should be in form "mmc:{guid}"
  487. // check for "mmc:"
  488. if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
  489. return sc = E_FAIL;
  490. // skip "mmc:"
  491. strURL += wcslen(szMMCC);
  492. // get the url
  493. sc = CLSIDFromString( const_cast<LPWSTR>(strURL), &guid );
  494. if (sc)
  495. return sc;
  496. return sc;
  497. }
  498. /***************************************************************************\
  499. *
  500. * METHOD: CMMCProtocol::ScParsePageBreakURL
  501. *
  502. * PURPOSE: Checks if URL given to the protocol is a request for a pagebreak
  503. *
  504. * PARAMETERS:
  505. * LPCWSTR strURL [in] - URL
  506. * bool& bPageBreak [out] - true it it is a request for pagebreak
  507. *
  508. * RETURNS:
  509. * SC - result code
  510. *
  511. \***************************************************************************/
  512. SC CMMCProtocol::ScParsePageBreakURL( LPCWSTR strURL, bool& bPageBreak )
  513. {
  514. DECLARE_SC(sc, TEXT("CMMCProtocol::ScParsePageBreakURL"));
  515. bPageBreak = false;
  516. sc = ScCheckPointers(strURL);
  517. if (sc)
  518. return sc;
  519. // pagebreak url should be in form "mmc:pagebreak.<number>"
  520. // check for "mmc:"
  521. if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
  522. return sc; // not an error - return value updated
  523. // skip "mmc:"
  524. strURL += wcslen(szMMCC);
  525. // get the url
  526. bPageBreak = ( 0 == wcsncmp( strURL, szPageBreak, wcslen(szPageBreak) ) );
  527. return sc;
  528. }
  529. /***************************************************************************\
  530. *
  531. * METHOD: CMMCProtocol::ScGetTaskpadXML
  532. *
  533. * PURPOSE: given the guid uploads taskpad XML string to the string
  534. *
  535. * PARAMETERS:
  536. * const GUID& guid [in] - taskpad guid
  537. * std::wstring& strResultData [out] - taskpad xml string
  538. *
  539. * RETURNS:
  540. * SC - result code
  541. *
  542. \***************************************************************************/
  543. SC CMMCProtocol::ScGetTaskpadXML( const GUID& guid, std::wstring& strResultData )
  544. {
  545. DECLARE_SC(sc, TEXT("CMMCProtocol::ScGetTaskpadXML"));
  546. strResultData.erase();
  547. CScopeTree* pScopeTree = CScopeTree::GetScopeTree();
  548. sc = ScCheckPointers(pScopeTree, E_FAIL);
  549. if(sc)
  550. return sc.ToHr();
  551. CConsoleTaskpadList * pConsoleTaskpadList = pScopeTree->GetConsoleTaskpadList();
  552. sc = ScCheckPointers(pConsoleTaskpadList, E_FAIL);
  553. if(sc)
  554. return sc.ToHr();
  555. for(CConsoleTaskpadList::iterator iter = pConsoleTaskpadList->begin(); iter!= pConsoleTaskpadList->end(); ++iter)
  556. {
  557. CConsoleTaskpad &consoleTaskpad = *iter;
  558. // check if this is the one we are looking for
  559. if ( !IsEqualGUID( guid, consoleTaskpad.GetID() ) )
  560. continue;
  561. // convert the taskpad to a string
  562. CStr strTaskpadHTML;
  563. sc = consoleTaskpad.ScGetHTML(strTaskpadHTML); // create a string version of the taskpad
  564. if(sc)
  565. return sc.ToHr();
  566. // form the result string
  567. USES_CONVERSION;
  568. strResultData = chUNICODE;
  569. strResultData += T2CW(strTaskpadHTML);
  570. return sc;
  571. }
  572. // not found
  573. return sc = E_FAIL;
  574. }
  575. /***************************************************************************\
  576. *
  577. * METHOD: CMMCProtocol::AppendMMCPath
  578. *
  579. * PURPOSE: helper. Appends the mmcndmgr.dll dir (no file name) to the string
  580. * It may append something like: "c:\winnt\system32"
  581. *
  582. * PARAMETERS:
  583. * std::wstring& str [in/out] - string to edit
  584. *
  585. * RETURNS:
  586. * SC - result code
  587. *
  588. \***************************************************************************/
  589. void CMMCProtocol::AppendMMCPath(std::wstring& str)
  590. {
  591. TCHAR szModule[_MAX_PATH+10] = { 0 };
  592. DWORD cchSize = countof(szModule);
  593. DWORD dwRet = GetModuleFileName(_Module.GetModuleInstance(), szModule, cchSize);
  594. if(0==dwRet)
  595. return;
  596. // NTRAID#NTBUG9-613782-2002/05/02-ronmart-prefast warning 53: Call to 'GetModuleFileNameW' may not zero-terminate string
  597. szModule[cchSize - 1] = 0;
  598. USES_CONVERSION;
  599. LPCWSTR strModule = T2CW(szModule);
  600. LPCWSTR dirEnd = wcsrchr( strModule, L'\\' );
  601. if (dirEnd != NULL)
  602. str.append(strModule, dirEnd);
  603. }
  604. /***************************************************************************\
  605. *
  606. * METHOD: CMMCProtocol::ExpandMMCVars
  607. *
  608. * PURPOSE: helper. expands any %mmcres% contained in the string
  609. * It expands it to something like "res://c:\winnt\system32\mmcndmgr.dll"
  610. *
  611. * PARAMETERS:
  612. * std::wstring& str [in/out] - string to edit
  613. *
  614. * RETURNS:
  615. * SC - result code
  616. *
  617. \***************************************************************************/
  618. void CMMCProtocol::ExpandMMCVars(std::wstring& str)
  619. {
  620. TCHAR szModule[_MAX_PATH+10] = { 0 };
  621. DWORD cchSize = countof(szModule);
  622. DWORD dwRet = GetModuleFileName(_Module.GetModuleInstance(), szModule, cchSize);
  623. if(0==dwRet)
  624. return;
  625. // NTRAID#NTBUG9-613782-2002/05/02-ronmart-prefast warning 53: Call to 'GetModuleFileNameW' may not zero-terminate string
  626. szModule[cchSize - 1] = 0;
  627. USES_CONVERSION;
  628. LPCWSTR strModule = T2CW(szModule);
  629. std::wstring mmcres = L"res://";
  630. mmcres += strModule;
  631. // second - replace the instances
  632. int pos;
  633. while (std::wstring::npos != (pos = str.find(szMMCRES) ) )
  634. {
  635. // make one substitution
  636. str.replace( pos, wcslen(szMMCRES), mmcres) ;
  637. }
  638. }