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.

700 lines
21 KiB

  1. // Moniker.cpp -- Implementation for the CStorageMoniker class
  2. #include "stdafx.h"
  3. HRESULT CStorageMoniker::CreateStorageMoniker
  4. (IUnknown *punkOuter,
  5. IBindCtx __RPC_FAR *pbc,
  6. LPOLESTR pszDisplayName,
  7. ULONG __RPC_FAR *pchEaten,
  8. IMoniker __RPC_FAR *__RPC_FAR *ppmkOut
  9. )
  10. {
  11. CStorageMoniker *pstmk = New CStorageMoniker(punkOuter);
  12. return FinishSetup(pstmk? pstmk->m_ImpIStorageMoniker.InitCreateStorageMoniker
  13. (pbc, pszDisplayName, pchEaten)
  14. : STG_E_INSUFFICIENTMEMORY,
  15. pstmk, IID_IMoniker, (PPVOID) ppmkOut
  16. );
  17. }
  18. CStorageMoniker::CImpIStorageMoniker::CImpIStorageMoniker
  19. (CStorageMoniker *pBackObj, IUnknown *punkOuter)
  20. : IITMoniker(pBackObj, punkOuter)
  21. {
  22. m_pStorageRoot = NULL;
  23. m_awszStorageFile[0] = 0;
  24. m_awszStoragePath[0] = 0;
  25. #ifdef IE30Hack
  26. m_acsTempFile [0] = 0;
  27. m_pcsDisplayName = NULL;
  28. #endif // IE30Hack
  29. }
  30. CStorageMoniker::CImpIStorageMoniker::~CImpIStorageMoniker(void)
  31. {
  32. if (m_pStorageRoot)
  33. m_pStorageRoot->Release();
  34. #ifdef IE30Hack
  35. if (m_pcsDisplayName)
  36. {
  37. UnlockUrlCacheEntryFile(m_pcsDisplayName, 0);
  38. delete [] m_pcsDisplayName;
  39. }
  40. if (m_acsTempFile[0])
  41. DeleteFile(m_acsTempFile);
  42. #endif // IE30Hack
  43. }
  44. HRESULT CStorageMoniker::CImpIStorageMoniker::InitCreateStorageMoniker
  45. (IBindCtx __RPC_FAR *pbc,
  46. LPOLESTR pszDisplayName,
  47. ULONG __RPC_FAR *pchEaten
  48. )
  49. {
  50. DWORD cwc = wcsLen(pszDisplayName) + 1;
  51. DWORD cb = cwc * sizeof(WCHAR);
  52. PWCHAR pwcsCopy = PWCHAR(_alloca(cwc * sizeof(WCHAR)));
  53. if (!pwcsCopy) return E_OUTOFMEMORY;
  54. memCpy(pwcsCopy, pszDisplayName, cb);
  55. PWCHAR pwcsExternal = NULL;
  56. PWCHAR pwcsInternal = NULL;
  57. PWCHAR pwcsProtocol = NULL;
  58. HRESULT hr = DisectUrl(pwcsCopy, &pwcsProtocol, &pwcsExternal, &pwcsInternal);
  59. if (!SUCCEEDED(hr))
  60. return (hr == INET_E_DEFAULT_ACTION)? INET_E_INVALID_URL : hr;
  61. wcsCpy(m_awszStorageFile, pwcsExternal);
  62. wcsCpy(m_awszStoragePath, pwcsInternal);
  63. cwc = wcsLen(m_awszStoragePath);
  64. if (m_awszStoragePath[cwc-1] == L'/')
  65. m_awszStoragePath[cwc-1] = 0;
  66. *pchEaten = cwc - 1;
  67. return NO_ERROR;
  68. }
  69. // IPersist methods
  70. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::GetClassID(
  71. /* [out] */ CLSID __RPC_FAR *pClassID)
  72. {
  73. *pClassID = CLSID_ITStorage;
  74. return NOERROR;
  75. }
  76. // IPersistStream methods
  77. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::IsDirty( void)
  78. {
  79. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  80. return E_NOTIMPL;
  81. }
  82. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Load(
  83. /* [unique][in] */ IStream __RPC_FAR *pStm)
  84. {
  85. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  86. return E_NOTIMPL;
  87. }
  88. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Save(
  89. /* [unique][in] */ IStream __RPC_FAR *pStm,
  90. /* [in] */ BOOL fClearDirty)
  91. {
  92. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  93. return E_NOTIMPL;
  94. }
  95. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::GetSizeMax(
  96. /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize)
  97. {
  98. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  99. return E_NOTIMPL;
  100. }
  101. // IMoniker methods
  102. /* [local] */ HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::BindToObject(
  103. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  104. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  105. /* [in] */ REFIID riidResult,
  106. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult)
  107. {
  108. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  109. return E_NOTIMPL;
  110. }
  111. #pragma data_seg(".text", "CODE")
  112. static const char txtTomeMapKey [] = ITSS_MAP;
  113. static const char txtTomeFinderKey[] = ITSS_FINDER;
  114. #pragma data_seg()
  115. HRESULT STDMETHODCALLTYPE FileExists(WCHAR *pwszStorageFile, const CHAR *pcsFullPath)
  116. {
  117. if (GetFileAttributes(pcsFullPath) == (DWORD) -1)
  118. return STG_E_FILENOTFOUND;
  119. // File exists! Now we need to convert the path to Unicode and store it.
  120. WCHAR awcsPath[MAX_PATH];
  121. UINT cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, pcsFullPath, -1,
  122. awcsPath, MAX_PATH
  123. );
  124. if (cwc == 0 || cwc > MAX_PATH)
  125. return STG_E_FILENOTFOUND;
  126. wcsCpy(pwszStorageFile, awcsPath);
  127. return S_OK;
  128. }
  129. char * __stdcall FindMBCSExtension(char *pcsFileName)
  130. {
  131. char *pchLastPeriod = NULL;
  132. for (;; pcsFileName = DBCS_SYSTEM()? CharNext(pcsFileName) : pcsFileName + 1)
  133. {
  134. char ch = *pcsFileName;
  135. if (!ch) break;
  136. if (ch != '.') continue;
  137. pchLastPeriod = pcsFileName;
  138. }
  139. return pchLastPeriod;
  140. }
  141. HRESULT STDMETHODCALLTYPE FindRootStorageFile(WCHAR * pwszStorageFile)
  142. {
  143. char csRoot [MAX_PATH * 2]; // * 2 for DBCS locales
  144. char csBuffer[MAX_PATH * 2];
  145. UINT cb = WideCharToMultiByte(CP_USER_DEFAULT(), WC_COMPOSITECHECK | WC_SEPCHARS,
  146. pwszStorageFile, 1 + wcsLen(pwszStorageFile),
  147. csRoot, sizeof(csRoot), NULL, NULL
  148. );
  149. if (cb == 0)
  150. return STG_E_INVALIDNAME;
  151. LPSTR pcsFileName = NULL;
  152. UINT cbFull = GetFullPathName(csRoot, sizeof(csBuffer), csBuffer, &pcsFileName);
  153. if (!cbFull || !pcsFileName)
  154. return STG_E_INVALIDNAME;
  155. HRESULT hr = FileExists(pwszStorageFile, (const char *) csBuffer);
  156. if (hr == S_OK) return hr;
  157. HKEY hkey;
  158. DWORD type;
  159. DWORD cbPath = MAX_PATH;
  160. LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, txtTomeMapKey, 0, KEY_READ, &hkey);
  161. if (result == ERROR_SUCCESS)
  162. {
  163. result = RegQueryValueEx(hkey, (const char *) pcsFileName, 0, &type,
  164. (PBYTE) csRoot, &cbPath
  165. );
  166. RegCloseKey(hkey);
  167. }
  168. if (result == ERROR_SUCCESS)
  169. {
  170. hr = FileExists(pwszStorageFile, (const char *) csRoot);
  171. if (hr == S_OK) return hr;
  172. }
  173. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, txtTomeFinderKey, 0, KEY_READ, &hkey);
  174. if (result == ERROR_SUCCESS)
  175. {
  176. result = RegQueryValueEx(hkey, (const char *) pcsFileName, 0, &type,
  177. (PBYTE) csRoot, &cbPath
  178. );
  179. if (result != ERROR_SUCCESS)
  180. {
  181. char *pcsFileExtension = FindMBCSExtension(pcsFileName);
  182. if (pcsFileExtension)
  183. result = RegQueryValueEx(hkey, pcsFileExtension, 0, &type,
  184. (PBYTE) csRoot, &cbPath
  185. );
  186. }
  187. RegCloseKey(hkey);
  188. }
  189. hr = STG_E_FILENOTFOUND;
  190. if (result == ERROR_SUCCESS)
  191. {
  192. CLSID clsid;
  193. WCHAR wcsFileName[MAX_PATH];
  194. UINT cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, csRoot, -1,
  195. wcsFileName, MAX_PATH
  196. );
  197. if (cwc != 0)
  198. {
  199. HRESULT hr2 = CLSIDFromString(wcsFileName, &clsid);
  200. if (hr2 == S_OK)
  201. {
  202. IITFileFinder *pFileFinder = NULL;
  203. cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, pcsFileName, -1,
  204. wcsFileName, MAX_PATH
  205. );
  206. if (cwc != 0)
  207. {
  208. hr2 = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IITFileFinder,
  209. (void **) &pFileFinder
  210. );
  211. if (hr2 == S_OK)
  212. __try
  213. {
  214. WCHAR *pwcsFullPath = NULL;
  215. BOOL fRecord = FALSE;
  216. hr2 = pFileFinder->FindThisFile((const WCHAR *) wcsFileName, &pwcsFullPath, &fRecord);
  217. // REMOVE THIS
  218. OutputDebugString("Moniker.cpp Find This File\n");
  219. OutputDebugStringW(wcsFileName);
  220. OutputDebugString("\n");
  221. // REMOVE THIS
  222. pFileFinder->Release(); pFileFinder = NULL;
  223. if (hr2 == S_OK)
  224. {
  225. RonM_ASSERT(pwcsFullPath);
  226. cb = WideCharToMultiByte(CP_USER_DEFAULT(), WC_COMPOSITECHECK | WC_SEPCHARS,
  227. pwcsFullPath, 1 + wcsLen(pwcsFullPath),
  228. csRoot, sizeof(csRoot), NULL, NULL
  229. );
  230. OLEHeap()->Free(pwcsFullPath);
  231. hr = (cb == 0)? STG_E_FILENOTFOUND
  232. : FileExists(pwszStorageFile, (const char *) csRoot);
  233. if (hr == S_OK && fRecord)
  234. {
  235. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, txtTomeMapKey, 0, KEY_READ, &hkey);
  236. if (result == ERROR_SUCCESS)
  237. {
  238. result = RegSetValueEx(hkey, (const char *) pcsFileName, 0, REG_SZ,
  239. (PBYTE) csRoot, lstrlen(csRoot)
  240. );
  241. RegCloseKey(hkey);
  242. }
  243. }
  244. }
  245. }
  246. __except (TRUE)
  247. {
  248. if (pFileFinder)
  249. pFileFinder->Release();
  250. };
  251. }
  252. }
  253. }
  254. }
  255. return hr;
  256. }
  257. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::OpenRootStorage
  258. (DWORD grfMode)
  259. {
  260. PWCHAR pwc = wcsChr((const WCHAR *) m_awszStorageFile, L':');
  261. if (pwc && pwc[1] == L':') // Ignore a "::" separator
  262. pwc = NULL;
  263. // Here we're special casing non-protocol references to a file.
  264. // We recognize those situations by looking for a protocol prefix.
  265. // Protocol prefixes have the form <Protocol Name> :
  266. // where <Protocol Name> is always longer than one character.
  267. if (!pwc || (pwc - m_awszStorageFile == 1))
  268. {
  269. HRESULT hr = FindRootStorageFile(m_awszStorageFile);
  270. if (hr != S_OK) return hr;
  271. return CITFileSystem::OpenITFileSystem(NULL, (const WCHAR *) m_awszStorageFile,
  272. grfMode, (IStorageITEx **)&m_pStorageRoot
  273. );
  274. }
  275. ILockBytes * plkbRoot = NULL;
  276. HRESULT hr = CStrmLockBytes::OpenUrlStream((const WCHAR *) m_awszStorageFile,
  277. &plkbRoot
  278. );
  279. if (hr == S_OK)
  280. hr = CITFileSystem::OpenITFSOnLockBytes(NULL, plkbRoot, grfMode,
  281. (IStorageITEx **)&m_pStorageRoot
  282. );
  283. if (plkbRoot)
  284. plkbRoot->Release();
  285. return hr;
  286. }
  287. const PWCHAR apwcsDefaultPages[5] = { L"/default.htm", L"/default.html",
  288. L"/index.htm", L"/index.html",
  289. NULL
  290. };
  291. /* [local] */ HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::BindToStorage(
  292. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  293. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  294. /* [in] */ REFIID riid,
  295. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj)
  296. {
  297. HRESULT hr = NOERROR;
  298. BIND_OPTS bo;
  299. bo.cbStruct = sizeof(bo);
  300. hr = pbc->GetBindOptions(&bo);
  301. // Streams and storages are always opened read-only with share deny-none
  302. // in the context of a URL.
  303. bo.grfMode &= ~(STGM_WRITE | STGM_READWRITE);
  304. bo.grfMode &= ~(STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ
  305. | STGM_SHARE_DENY_WRITE
  306. | STGM_SHARE_EXCLUSIVE
  307. );
  308. bo.grfMode |= STGM_SHARE_DENY_NONE;
  309. if (hr != S_OK) return hr;
  310. if (!m_pStorageRoot)
  311. {
  312. hr = OpenRootStorage(bo.grfMode);
  313. if (hr != S_OK) return hr;
  314. }
  315. if (riid == IID_IStorage)
  316. hr = m_pStorageRoot->OpenStorage(m_awszStoragePath, NULL, bo.grfMode,
  317. NULL, 0, (IStorage **) ppvObj
  318. );
  319. else
  320. if (riid == IID_IStream)
  321. {
  322. hr = m_pStorageRoot->OpenStream(m_awszStoragePath, NULL, bo.grfMode,
  323. 0, (IStream **) ppvObj
  324. );
  325. if (!SUCCEEDED(hr))
  326. {
  327. const PWCHAR *ppwcsDefPages = apwcsDefaultPages;
  328. for (;;)
  329. {
  330. const PWCHAR pwcsDefPage = *ppwcsDefPages++;
  331. if (!pwcsDefPage) break;
  332. WCHAR awszDefault[MAX_PATH];
  333. wcsCpy(awszDefault, m_awszStoragePath);
  334. UINT cwc= wcsLen(m_awszStoragePath) + wcsLen(pwcsDefPage);
  335. if (cwc < MAX_PATH)
  336. {
  337. wcsCat(awszDefault, pwcsDefPage);
  338. hr = m_pStorageRoot->OpenStream(awszDefault, NULL, bo.grfMode,
  339. 0, (IStream **) ppvObj
  340. );
  341. if (SUCCEEDED(hr))
  342. {
  343. wcsCpy(m_awszStoragePath, awszDefault);
  344. break;
  345. }
  346. }
  347. }
  348. }
  349. }
  350. else return E_NOINTERFACE;
  351. #ifdef IE30Hack
  352. // The following code is a slimey hack to work around a defect in the IE 3.0x
  353. // URLMon code. The problem is that IE 3.0 treats the trailing part of our URL
  354. // as if it were a file name, and that makes many things break.
  355. //
  356. // The code below crawls up the stack and follows several pointers to locate the
  357. // incorrect file name and fix it to point to a file which a copy of the stream
  358. // we've just opened.
  359. if (SUCCEEDED(hr) && !IS_IE4()) // Running in IE 3.0x ???
  360. {
  361. PWCHAR pwcsDisplayName = NULL;
  362. // We use a try/except bracket to recover from crawl failures.
  363. __try
  364. {
  365. // First we compute stack frame pointers for BindToStorage
  366. // and the next higher frame.
  367. DWORD *pdwFrame = ((DWORD *) &pbc) - 3;
  368. DWORD *pdwFrameNext = (DWORD *) *pdwFrame;
  369. DWORD *pdwCINet;
  370. // We're looking for a pointer to a CINetStream object. That pointer
  371. // is located at different places in the retail and debug builds
  372. // of URLMon.
  373. if (pdwFrameNext - pdwFrame > 0x1b6)
  374. pdwCINet = (DWORD *) pdwFrameNext[5]; // Debug build
  375. else pdwCINet = (DWORD *) pdwFrame [8]; // Retail build
  376. // From there we can get the pointer to the transaction object.
  377. PBYTE pbTransData = (PBYTE) pdwCINet[0x8de];
  378. // Then the transaction object contains the erroneous
  379. // file paths.
  380. PWCHAR pwcsFilePath = (PWCHAR) (pbTransData + 0xC );
  381. PCHAR pcsFilePath = ( PCHAR) (pbTransData + 0x284);
  382. hr = GetDisplayName(pbc, NULL, &pwcsDisplayName);
  383. if ( SUCCEEDED(hr)
  384. && !wcsicmp_0x0409((const WCHAR *) pwcsDisplayName + 14, (const WCHAR *)pwcsFilePath)
  385. )
  386. {
  387. #ifdef _DEBUG
  388. HRESULT hr2 =
  389. #endif // _DEBUG
  390. StreamToIEFile((IStream *) *ppvObj, pwcsDisplayName, m_pcsDisplayName,
  391. pcsFilePath, pwcsFilePath, m_acsTempFile,
  392. (IMoniker *) this, FALSE, FALSE
  393. );
  394. RonM_ASSERT(SUCCEEDED(hr2));
  395. }
  396. }
  397. __except (EXCEPTION_EXECUTE_HANDLER)
  398. {
  399. }
  400. if (pwcsDisplayName)
  401. OLEHeap()->Free(pwcsDisplayName);
  402. }
  403. #endif // IE30Hack
  404. return hr;
  405. }
  406. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Reduce(
  407. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  408. /* [in] */ DWORD dwReduceHowFar,
  409. /* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
  410. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced)
  411. {
  412. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  413. return E_NOTIMPL;
  414. }
  415. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::ComposeWith(
  416. /* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
  417. /* [in] */ BOOL fOnlyIfNotGeneric,
  418. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite)
  419. {
  420. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  421. return E_NOTIMPL;
  422. }
  423. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Enum(
  424. /* [in] */ BOOL fForward,
  425. /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker)
  426. {
  427. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  428. return E_NOTIMPL;
  429. }
  430. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::IsEqual(
  431. /* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker)
  432. {
  433. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  434. return E_NOTIMPL;
  435. }
  436. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Hash(
  437. /* [out] */ DWORD __RPC_FAR *pdwHash)
  438. {
  439. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  440. return E_NOTIMPL;
  441. }
  442. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::IsRunning(
  443. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  444. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  445. /* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning)
  446. {
  447. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  448. return E_NOTIMPL;
  449. }
  450. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::GetTimeOfLastChange(
  451. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  452. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  453. /* [out] */ FILETIME __RPC_FAR *pFileTime)
  454. {
  455. STATSTG statstg;
  456. HRESULT hr = m_pStorageRoot->Stat(&statstg, STATFLAG_NONAME);
  457. if (!SUCCEEDED(hr))
  458. return hr;
  459. if (pFileTime)
  460. *pFileTime = statstg.mtime;
  461. return NO_ERROR;
  462. }
  463. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::Inverse(
  464. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk)
  465. {
  466. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  467. return E_NOTIMPL;
  468. }
  469. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::CommonPrefixWith(
  470. /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
  471. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix)
  472. {
  473. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  474. return E_NOTIMPL;
  475. }
  476. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::RelativePathTo(
  477. /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
  478. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath)
  479. {
  480. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  481. return E_NOTIMPL;
  482. }
  483. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::GetDisplayName(
  484. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  485. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  486. /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName)
  487. {
  488. UINT cwcExternalPath = wcsLen(m_awszStorageFile);
  489. UINT cwcInternalPath = wcsLen(m_awszStoragePath);
  490. UINT cwcDisplayName = (IS_IE4()? 9 : 16) + cwcExternalPath + cwcInternalPath;
  491. PWCHAR pwcsDisplayName = PWCHAR(OLEHeap()->Alloc(sizeof(WCHAR) * (cwcDisplayName + 1)));
  492. if (!pwcsDisplayName)
  493. return E_OUTOFMEMORY;
  494. wcsCpy(pwcsDisplayName, IS_IE4()? L"ms-its:" :L"mk:@msitstore:");
  495. wcsCat(pwcsDisplayName, m_awszStorageFile);
  496. wcsCat(pwcsDisplayName, L"::");
  497. wcsCat(pwcsDisplayName, m_awszStoragePath);
  498. *ppszDisplayName = pwcsDisplayName;
  499. return NO_ERROR;
  500. }
  501. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::ParseDisplayName(
  502. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  503. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  504. /* [in] */ LPOLESTR pszDisplayName,
  505. /* [out] */ ULONG __RPC_FAR *pchEaten,
  506. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut)
  507. {
  508. RonM_ASSERT(FALSE); // To catch unexpected uses of this interface...
  509. return E_NOTIMPL;
  510. }
  511. HRESULT STDMETHODCALLTYPE CStorageMoniker::CImpIStorageMoniker::IsSystemMoniker(
  512. /* [out] */ DWORD __RPC_FAR *pdwMksys)
  513. {
  514. return MKSYS_NONE;
  515. }