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.

1684 lines
39 KiB

  1. //+=======================================================================
  2. //
  3. // File: CMoniker.cxx
  4. //
  5. // Purpose: Define the CMoniker class.
  6. //
  7. // This class provides for all handling of monikers in
  8. // the CreateFileMonikerEx DRT. Not only does it maintain
  9. // a file moniker, it also maintains the represented link
  10. // source file, and a bind context.
  11. //
  12. //+=======================================================================
  13. // --------
  14. // Includes
  15. // --------
  16. #define _DCOM_ // Allow DCOM extensions (e.g., CoInitializeEx).
  17. #include <windows.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <wchar.h>
  21. #include <wtypes.h>
  22. #include <oaidl.h>
  23. #include <dsys.h>
  24. #include <olecairo.h>
  25. #include "CFMEx.hxx"
  26. #include "CMoniker.hxx"
  27. //+-------------------------------------------------------------------------
  28. //
  29. // Function: CMoniker::CMoniker
  30. //
  31. // Synopsis: Simply initialize all member variables.
  32. //
  33. // Inputs: None.
  34. //
  35. // Outputs: N/A
  36. //
  37. // Effects: Members are defaulted/initialized.
  38. //
  39. //+-------------------------------------------------------------------------
  40. CMoniker::CMoniker()
  41. {
  42. *m_wszSystemTempPath = L'\0';
  43. *m_wszTemporaryStorage = L'\0';
  44. m_pIMoniker = NULL;
  45. m_pIBindCtx = NULL;
  46. m_pIStorage = NULL;
  47. *m_wszErrorMessage = L'\0';
  48. m_dwTrackFlags = 0L;
  49. m_hkeyLinkTracking = NULL;
  50. m_hr = 0L;
  51. m_bSuppressErrorMessages = FALSE;
  52. m_pcDirectoryOriginal = NULL;
  53. m_pcDirectoryFinal = NULL;
  54. return;
  55. } // CMoniker::CMoniker()
  56. //+--------------------------------------------------------------------------
  57. //
  58. // Function: CMoniker::~CMoniker
  59. //
  60. // Synopsis: Release any COM objects.
  61. //
  62. // Inputs: N/A
  63. //
  64. // Outputs: N/A
  65. //
  66. // Effects: All COM objects are released.
  67. //
  68. //+--------------------------------------------------------------------------
  69. CMoniker::~CMoniker()
  70. {
  71. if( m_pIMoniker )
  72. {
  73. m_pIMoniker->Release();
  74. m_pIMoniker = NULL;
  75. }
  76. if( m_pIBindCtx )
  77. {
  78. m_pIBindCtx->Release();
  79. m_pIBindCtx = NULL;
  80. }
  81. if( m_pIStorage )
  82. {
  83. m_pIStorage->Release();
  84. m_pIStorage = NULL;
  85. }
  86. return;
  87. } // CMoniker::~CMoniker()
  88. //+-----------------------------------------------------------------------
  89. //
  90. // Function: CMoniker::Initialize
  91. //
  92. // Synopsis: Keep pointers to the CDirectory objects passed in.
  93. //
  94. // Inputs: A CDirectory object for the original link source file location
  95. // A CDirectory object for the final location
  96. //
  97. // Outputs: TRUE if successful, FALSE otherwise.
  98. //
  99. // Effects: The member CDirectory objects are set.
  100. //
  101. //+-----------------------------------------------------------------------
  102. BOOL CMoniker::Initialize( const CDirectory& cDirectoryOriginal,
  103. const CDirectory& cDirectoryFinal )
  104. {
  105. m_hr = S_OK;
  106. m_pcDirectoryOriginal = &cDirectoryOriginal;
  107. m_pcDirectoryFinal = &cDirectoryFinal;
  108. return( TRUE ); // Success
  109. } // CMoniker::Initialize()
  110. //+-----------------------------------------------------------------------------
  111. //
  112. // Function: CMoniker::CreateFileMonikerEx
  113. //
  114. // Synopsis: Create a tracking file moniker. But before doing so, initialize
  115. // the Bind Context, and create a link source file.
  116. //
  117. // Inputs: Track Flags (from the TRACK_FLAGS defines)
  118. //
  119. // Outputs: TRUE if successful, FALSE otherwise.
  120. //
  121. // Effects: The member bind context is initialized, and a link
  122. // source file is created.
  123. //
  124. //+-----------------------------------------------------------------------------
  125. BOOL CMoniker::CreateFileMonikerEx( DWORD dwTrackFlags )
  126. {
  127. // ---------------
  128. // Local Variables
  129. // ---------------
  130. // Assume failure
  131. BOOL bSuccess = FALSE;
  132. // -----
  133. // Begin
  134. // -----
  135. // Initialize the error code.
  136. m_hr = S_OK;
  137. // Free any existing IMoniker.
  138. if( m_pIMoniker )
  139. {
  140. m_pIMoniker->Release();
  141. m_pIMoniker = NULL;
  142. }
  143. // Initialize the bind context.
  144. if( !InitializeBindContext() )
  145. EXIT( L"Could not initialize the bind context" );
  146. // Create a root storage for use as a link source.
  147. if( !CreateTemporaryStorage() )
  148. EXIT( L"Could not create temporary Storage" );
  149. // Create a tracking File Moniker on that root storage.
  150. m_hr = ::CreateFileMonikerEx( dwTrackFlags, m_wszTemporaryStorage, &m_pIMoniker );
  151. EXIT_ON_FAILED( L"Failed CreateFileMonikerEx" );
  152. bSuccess = TRUE;
  153. // ----
  154. // Exit
  155. // ----
  156. Exit:
  157. DisplayErrors( bSuccess, L"CMoniker::CreateFileMonikerEx" );
  158. return( bSuccess );
  159. } // CMoniker::CreateFileMonikerEx()
  160. //+---------------------------------------------------------------------
  161. //
  162. // Function: CMoniker::SaveDeleteLoad
  163. //
  164. // Synopsis: This function exercises a moniker's IPersistStream interface.
  165. // It creates saves the member moniker's persistent state to
  166. // a stream, deletes the moniker, and then re-creates it
  167. // using CreateFileMoniker (no Ex, so it's not a tracking
  168. // file moniker). It then re-loads the original moniker's
  169. // persistent state.
  170. //
  171. // Inputs: None.
  172. //
  173. // Outputs: TRUE if successful, FALSE otherwise.
  174. //
  175. // Effects: The member moniker is deleted, re-created, and re-loaded.
  176. //
  177. //+---------------------------------------------------------------------
  178. BOOL CMoniker::SaveDeleteLoad()
  179. {
  180. // ---------------
  181. // Local Variables
  182. // ---------------
  183. // Assume failure
  184. BOOL bSuccess = FALSE;
  185. HRESULT hr = E_FAIL;
  186. IStream* pStream = NULL;
  187. IPersistStream* pIPersistStream = NULL;
  188. LARGE_INTEGER li;
  189. ULARGE_INTEGER uli;
  190. // -----
  191. // Begin
  192. // -----
  193. // Initialize the error code.
  194. m_hr = S_OK;
  195. // Verify that we have a member moniker.
  196. if( !m_pIMoniker )
  197. EXIT( L"Attempt to run SaveDeleteLoad test without an existing file moniker" );
  198. // ------------------------
  199. // Save the moniker's state
  200. // ------------------------
  201. // Get the moniker's IPersistStream interface
  202. m_hr = m_pIMoniker->QueryInterface( IID_IPersistStream, (void **) &pIPersistStream );
  203. EXIT_ON_FAILED( L"Failed 1st IMoniker::QueryInterface(IPersistStream)" );
  204. // Create a stream
  205. hr = CreateStreamOnHGlobal( NULL, // Auto alloc
  206. TRUE, // Delete on release
  207. &pStream );
  208. EXIT_ON_FAILED( L"Failed CreateStreamOnHGlobal()" );
  209. // Save the moniker's state to this stream.
  210. hr = pIPersistStream->Save( pStream, TRUE /* Clear dirty*/ );
  211. EXIT_ON_FAILED( L"Failed IPersistStream::Save()" );
  212. // ------------------
  213. // Delete the moniker
  214. // ------------------
  215. // Release all interfaces for the moniker.
  216. m_pIMoniker->Release();
  217. pIPersistStream->Release();
  218. m_pIMoniker = NULL;
  219. pIPersistStream = NULL;
  220. // --------------------
  221. // Create a new moniker
  222. // --------------------
  223. // Create a new moniker, using the non-Ex version of the function.
  224. m_hr = ::CreateFileMoniker( m_wszTemporaryStorage, &m_pIMoniker );
  225. EXIT_ON_FAILED( L"Failed CreateFileMoniker()" );
  226. // --------------------
  227. // Load the new moniker
  228. // --------------------
  229. // Get the IPersisStream interface
  230. m_hr = m_pIMoniker->QueryInterface( IID_IPersistStream, (void **) &pIPersistStream );
  231. EXIT_ON_FAILED( L"Failed 2nd IMoniker::QueryInterface(IPersistStream)" );
  232. // Re-seek the stream to the beginning.
  233. li.LowPart = li.HighPart = 0L;
  234. hr = pStream->Seek( li, STREAM_SEEK_SET, &uli );
  235. EXIT_ON_FAILED( L"Failed IStream::Seek()" );
  236. if( uli.LowPart || uli.HighPart ) EXIT( L"Incorrect IStream::Seek()" );
  237. // Re-load the moniker from the stream.
  238. m_hr = pIPersistStream->Load( pStream );
  239. EXIT_ON_FAILED( L"Failed IPersistStream::Load()" );
  240. bSuccess = TRUE;
  241. // ----
  242. // Exit
  243. // ----
  244. Exit:
  245. // Clean up the stream and the IPersistStream interface.
  246. if( pStream )
  247. pStream->Release;
  248. if( pIPersistStream )
  249. pIPersistStream->Release();
  250. DisplayErrors( bSuccess, L"CMoniker::SaveDeleteLoad()" );
  251. return( bSuccess );
  252. } // CMoniker::SaveDeleteLoad()
  253. //+------------------------------------------------------------------
  254. //
  255. // Function: CMoniker::ComposeWith
  256. //
  257. // Synopsis: Compose a tracking moniker with a non-tracking moniker
  258. // on the right. (The resulting moniker should be tracking,
  259. // but this is not relevant to this function; that is, whether
  260. // or not the composed moniker is tracking, this function will
  261. // succeed.)
  262. //
  263. // Inputs: None.
  264. //
  265. // Output: TRUE if successful, FALSE otherwise.
  266. //
  267. // Effects: The member moniker is deleted, then recreated.
  268. //
  269. //+------------------------------------------------------------------
  270. BOOL CMoniker::ComposeWith()
  271. {
  272. // ---------------
  273. // Local Variables
  274. // ---------------
  275. BOOL bSuccess = FALSE;
  276. IMoniker* pmkrFirst = NULL;
  277. IMoniker* pmkrSecond = NULL;
  278. HRESULT hr = E_FAIL;
  279. WCHAR wszDirectoryName[ MAX_PATH + sizeof( L'\0' ) ];
  280. WCHAR* wszFileName = NULL;
  281. // -----
  282. // Begin
  283. // -----
  284. // Initiailize the error code.
  285. m_hr = S_OK;
  286. // If we have a moniker already, delete it.
  287. if( m_pIMoniker )
  288. {
  289. m_pIMoniker->Release();
  290. m_pIMoniker = NULL;
  291. }
  292. // Verify we already have a link source file created.
  293. if( !wcslen( m_wszTemporaryStorage ) )
  294. EXIT( L"Attempt to use ComposeWith without first creating a link source.\n" );
  295. // -----------------------------------------------
  296. // Create a tracking and non-tracking file moniker
  297. // -----------------------------------------------
  298. // Parse the storage's filename into a path and a file ...
  299. // for example, "C:\Temp\file.tmp" would become
  300. // "C:\Temp" and "file.tmp".
  301. //
  302. // First, make a copy of the storage's complete path name,
  303. // then replace the last '\\' with a '\0', thus creating two
  304. // strings.
  305. wcscpy( wszDirectoryName, m_wszTemporaryStorage );
  306. wszFileName = wcsrchr( wszDirectoryName, L'\\' );
  307. *wszFileName = L'\0';
  308. wszFileName++;
  309. // Create a tracking file moniker using the directory name.
  310. m_hr = ::CreateFileMonikerEx( 0L, wszDirectoryName, &pmkrFirst );
  311. EXIT_ON_FAILED( L"Failed 1st CreateFileMoniker()" );
  312. // Create a non-tracking file moniker using the file name.
  313. m_hr = ::CreateFileMoniker( wszFileName, &pmkrSecond );
  314. EXIT_ON_FAILED( L"Failed 2nd CreateFileMoniker()" );
  315. // -------
  316. // Compose
  317. // -------
  318. // Compose the directory name moniker (on the left) with the file name moniker
  319. // (on the right). Put the result in the member moniker.
  320. m_hr = pmkrFirst->ComposeWith( pmkrSecond, TRUE, &m_pIMoniker );
  321. EXIT_ON_FAILED( L"Failed IMoniker::ComposeWith" );
  322. bSuccess = TRUE;
  323. // ----
  324. // Exit
  325. // ----
  326. Exit:
  327. // Clean up the intermediary monikers.
  328. if( pmkrFirst )
  329. pmkrFirst->Release();
  330. if( pmkrSecond )
  331. pmkrSecond->Release();
  332. DisplayErrors( bSuccess, L"CMoniker::ComposeWith()" );
  333. return( bSuccess );
  334. } // CMoniker::ComposeWith()
  335. //+--------------------------------------------------------------------
  336. //
  337. // Function: CMoniker::CreateTemporaryStorage
  338. //
  339. // Synopsis: This function creates a Structured Storage
  340. // in the directory identified by m_cDirectoryOriginal.
  341. // The name of the file is randomly generated by the system,
  342. // but begins with "MKR" and has the extension ".tmp".
  343. //
  344. // Inputs: None.
  345. //
  346. // Output: TRUE if successful, FALSE otherwise.
  347. //
  348. // Effects: Stores the Structure Storage's name in
  349. // m_wszTemporaryStorageName, and releases m_pIStorage if
  350. // it is currently set.
  351. //
  352. //+--------------------------------------------------------------------
  353. BOOL CMoniker::CreateTemporaryStorage()
  354. {
  355. // ---------------
  356. // Local Variables
  357. // ---------------
  358. BOOL bSuccess = FALSE;
  359. DWORD dwError = 0L;
  360. UINT nError = 0;
  361. // -----
  362. // Begin
  363. // -----
  364. m_hr = S_OK;
  365. // Delete any existing storage.
  366. if( wcslen( m_wszTemporaryStorage ))
  367. {
  368. if( !DeleteTemporaryStorage() )
  369. EXIT( L"Could not delete the existing temporary storage" );
  370. }
  371. // Generate a temporary filename.
  372. nError = GetTempFileName( m_pcDirectoryOriginal->GetDirectoryName(),
  373. L"MKR", // Prefix string.
  374. 0, // Generate random number,
  375. m_wszTemporaryStorage );
  376. if( nError == 0 )
  377. {
  378. m_hr = (HRESULT) GetLastError();
  379. EXIT( L"Failed GetTempFileName()" );
  380. }
  381. // Create a root Storage.
  382. m_hr = StgCreateDocfile( m_wszTemporaryStorage,
  383. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
  384. 0L, // Reserved
  385. &m_pIStorage );
  386. EXIT_ON_FAILED( L"Failed StgCreateDocfile()" );
  387. // Release the storage.
  388. m_pIStorage->Release();
  389. m_pIStorage = NULL;
  390. bSuccess = TRUE;
  391. // ----
  392. // Exit
  393. // ----
  394. Exit:
  395. DisplayErrors( bSuccess, L"CMoniker::CreateTemporaryStorage()" );
  396. return( bSuccess );
  397. } // CMoniker::CreateTemporaryStorage()
  398. //+-------------------------------------------------------------------------
  399. //
  400. // Function: CMoniker::RenameTemporaryStorage
  401. //
  402. // Synopsis: Rename the link source file (who's name is in m_wszTemporaryStorage)
  403. // to the m_cDirectoryFinal directory, with a new name.
  404. // The current name is "MKR#.tmp" (where "#" is a random number
  405. // generated by the system), and the new name is "RKM#.tmp" (where
  406. // "#" is the same random number). (We must rename the base file
  407. // name, rather than its extension, because otherwise the default
  408. // link-tracking would fail (it would only score the renamed file
  409. // a 32 - by matching the file extension the score is 40.)
  410. //
  411. // Inputs: None.
  412. //
  413. // Output: TRUE if successful, FALSE otherwise.
  414. //
  415. // Effects: The link source file is renamed, and it's new name is
  416. // put into m_wszTemporaryStorage.
  417. //
  418. //+-------------------------------------------------------------------------
  419. BOOL CMoniker::RenameTemporaryStorage()
  420. {
  421. // ---------------
  422. // Local Variables
  423. // ---------------
  424. BOOL bSuccess = FALSE;
  425. int nError = 0;
  426. WCHAR wszNewName[ MAX_PATH + sizeof( L'\0' ) ];
  427. WCHAR* wszOldFileName;
  428. WCHAR wszNewFileName[ MAX_PATH + sizeof( L'\0' ) ];
  429. char szOldName[ MAX_PATH + sizeof( L'\0' ) ];
  430. char szNewName[ MAX_PATH + sizeof( L'\0' ) ];
  431. // -----
  432. // Begin
  433. // -----
  434. m_hr = S_OK;
  435. // Verify that we already have a link source created.
  436. if( !wcslen( m_wszTemporaryStorage ))
  437. EXIT( L"No temporary storage to rename." );
  438. // Locate the file name within the complete path.
  439. // (E.g., find the "foo.txt" in "C:\TEMP\foot.txt".)
  440. wszOldFileName = wcsrchr( m_wszTemporaryStorage, L'\\' );
  441. if( !wszOldFileName )
  442. EXIT( L"Could not extract old file name from temporary storage name\n" );
  443. wszOldFileName++; // Get past the '\\'
  444. // Generate the new file name (change "MKR" to "RKM").
  445. wcscpy( wszNewFileName, wszOldFileName );
  446. wszNewFileName[0] = L'R';
  447. wszNewFileName[1] = L'K';
  448. wszNewFileName[2] = L'M';
  449. // Generate the complete path spec of the new file.
  450. wcscpy( wszNewName, m_pcDirectoryFinal->GetDirectoryName() );
  451. wcscat( wszNewName, wszNewFileName );
  452. // Convert the new and old file names to ANSI.
  453. if( m_hr = UnicodeToAnsi( m_wszTemporaryStorage, szOldName, sizeof( szOldName )) )
  454. {
  455. EXIT( L"Could not convert convert Unicode to Ansi for old name" );
  456. }
  457. if( m_hr = UnicodeToAnsi( wszNewName, szNewName, sizeof( szNewName )) )
  458. {
  459. EXIT( L"Could not convert convert Unicode to Ansi for new name" );
  460. }
  461. // Rename the file.
  462. nError = rename( szOldName, szNewName );
  463. if( nError )
  464. {
  465. m_hr = (HRESULT) errno;
  466. EXIT( L"Failed rename()" );
  467. }
  468. // Record the new name.
  469. wcscpy( m_wszTemporaryStorage, wszNewName );
  470. bSuccess = TRUE;
  471. // ----
  472. // Exit
  473. // ----
  474. Exit:
  475. DisplayErrors( bSuccess, L"CMoniker::RenameTemporaryStorage()" );
  476. return( bSuccess );
  477. } // CMoniker::RenameTemporaryStorage()
  478. //+--------------------------------------------------------------------
  479. //
  480. // Function: CMoniker::DeleteTemporaryStorage
  481. //
  482. // Synopsis: Delete the temporary storage that this object uses
  483. // as a link source for the moniker. The name of the
  484. // storage is in m_wszTemporaryStorage.
  485. //
  486. // Inputs: None.
  487. //
  488. // Output: TRUE if successful, FALSE otherwise.
  489. //
  490. // Effects: The link source file is deleted, and m_wszTemporaryStorage
  491. // is set to a NULL string.
  492. //
  493. //+--------------------------------------------------------------------
  494. BOOL CMoniker::DeleteTemporaryStorage()
  495. {
  496. // ---------------
  497. // Local Variables
  498. // ---------------
  499. BOOL bSuccess = FALSE;
  500. int nError = 0;
  501. CHAR szTemporaryStorage[ MAX_PATH + sizeof( '\0' ) ];
  502. // -----
  503. // Begin
  504. // -----
  505. m_hr = S_OK;
  506. // Don't do anything if we have no file (don't report an
  507. // error either; the caller wants the file deleted, and it's
  508. // already not there).
  509. if( wcslen( m_wszTemporaryStorage ))
  510. {
  511. // Get the file name in ANSI.
  512. if( m_hr = UnicodeToAnsi( m_wszTemporaryStorage, szTemporaryStorage, sizeof( szTemporaryStorage )))
  513. EXIT( L"Could not convert unicode path to ANSI path" );
  514. // Delete the file.
  515. nError = unlink( szTemporaryStorage );
  516. if( nError )
  517. {
  518. m_hr = (HRESULT) errno;
  519. EXIT( L"Failed unlink()" );
  520. }
  521. // Clear the file name.
  522. wcscpy( m_wszTemporaryStorage, L"" );
  523. }
  524. bSuccess = TRUE;
  525. // ----
  526. // Exit
  527. // ----
  528. Exit:
  529. DisplayErrors( bSuccess, L"CMoniker::DeleteTemporaryStorage()" );
  530. return( bSuccess );
  531. } // CMoniker::DeleteTemporaryStorage()
  532. //+-----------------------------------------------------------------
  533. //
  534. // Function: CMoniker::Reduce
  535. //
  536. // Synopsis: Perform a IMoniker::Reduce on the member moniker.
  537. //
  538. // Inputs: - Number of ticks until the deadline for completion of
  539. // the operation.
  540. // - A buffer into which to put the reduced IMoniker*
  541. // (may be NULL).
  542. //
  543. // Output: TRUE if successful, FALSE otherwise.
  544. //
  545. // Effects: None.
  546. //
  547. //+-----------------------------------------------------------------
  548. BOOL CMoniker::Reduce( DWORD dwDelay, IMoniker** ppmkReturn )
  549. {
  550. // ---------------
  551. // Local Variables
  552. // ---------------
  553. BOOL bSuccess = FALSE;
  554. IMoniker* pmkReduced = NULL;
  555. BIND_OPTS2 bind_opts;
  556. bind_opts.cbStruct = sizeof( BIND_OPTS2 );
  557. // -----
  558. // Begin
  559. // -----
  560. m_hr = S_OK;
  561. // ----------
  562. // Initialize
  563. // ----------
  564. // Initialize the return buffer, if extant.
  565. if( ppmkReturn )
  566. *ppmkReturn = NULL;
  567. // Validate our state.
  568. if( !m_pIMoniker )
  569. EXIT( L"No moniker exists to be reduced" );
  570. // ----------------
  571. // Set the deadline
  572. // ----------------
  573. // Get the BIND_OPTS from the bind context.
  574. m_hr = m_pIBindCtx->GetBindOptions( (LPBIND_OPTS) &bind_opts );
  575. EXIT_ON_FAILED( L"Failed IBindCtx::GetBindOptions" );
  576. // Determine what the tick count of the deadline is.
  577. if( dwDelay == INFINITE )
  578. {
  579. bind_opts.dwTickCountDeadline = 0;
  580. }
  581. else
  582. {
  583. bind_opts.dwTickCountDeadline = GetTickCount() + dwDelay;
  584. // Make sure the resulting tick count is not 0 (indicating no
  585. // deadline).
  586. if( bind_opts.dwTickCountDeadline == 0 )
  587. bind_opts.dwTickCountDeadline++;
  588. }
  589. // Put the resulting BIND_OPTS back into the bind context.
  590. m_hr = m_pIBindCtx->SetBindOptions( (LPBIND_OPTS) &bind_opts );
  591. EXIT_ON_FAILED( L"Failed IBindCtx::SetBindOptions" );
  592. // ------------------
  593. // Reduce the Moniker
  594. // ------------------
  595. m_hr = m_pIMoniker->Reduce( m_pIBindCtx,
  596. MKRREDUCE_ALL,
  597. NULL,
  598. &pmkReduced );
  599. EXIT_ON_FAILED( L"Failed IMoniker::Reduce" );
  600. // Return the reduced moniker to the caller (if so requested).
  601. if( ppmkReturn )
  602. {
  603. // Transfer responsibility for the release to the caller.
  604. *ppmkReturn = pmkReduced;
  605. pmkReduced = NULL;
  606. }
  607. bSuccess = TRUE;
  608. // ----
  609. // Exit
  610. // ----
  611. Exit:
  612. DisplayErrors( bSuccess, L"CMoniker::Reduce()" );
  613. if( pmkReduced )
  614. pmkReduced->Release();
  615. return( bSuccess );
  616. } // CMoniker::Reduce()
  617. //+----------------------------------------------------------------------
  618. //
  619. // Function: CMoniker::GetDisplayName
  620. //
  621. // Synopsis: Get the moniker's display name.
  622. //
  623. // Inputs: A Unicode buffer for the display name, and (optionally)
  624. // a moniker from which to get the display name. If such
  625. // a moniker is not provided by the caller, then the member
  626. // moniker is used.
  627. //
  628. // The unicode buffer must be long enough for MAX_PATH characters
  629. // and a terminating NULL.
  630. //
  631. // Outputs: TRUE if successful, FALSE otherwise.
  632. //
  633. // Effects: None.
  634. //
  635. //+----------------------------------------------------------------------
  636. BOOL CMoniker::GetDisplayName( WCHAR * wszDisplayName, IMoniker* pmnkCaller )
  637. {
  638. // ---------------
  639. // Local Variables
  640. // ---------------
  641. BOOL bSuccess = FALSE;
  642. WCHAR* wszReturnedDisplayName = NULL;
  643. IMoniker* pmnk = NULL;
  644. // -----
  645. // Begin
  646. // -----
  647. m_hr = NOERROR;
  648. // Determine which moniker to use, the caller-specified one or
  649. // the member one.
  650. if( pmnkCaller != NULL )
  651. pmnk = pmnkCaller;
  652. else
  653. pmnk = m_pIMoniker;
  654. if( !pmnk )
  655. EXIT( L"Attempt to GetDisplayName on NULL moniker" );
  656. // Get the display name from the moniker.
  657. m_hr = pmnk->GetDisplayName( m_pIBindCtx,
  658. NULL,
  659. &wszReturnedDisplayName );
  660. EXIT_ON_FAILED( L"Failed IMoniker::GetDisplayName()" );
  661. if( wcslen( wszReturnedDisplayName ) > MAX_UNICODE_PATH )
  662. EXIT( L"IMoniker::GetDisplayName() returned a path which was too long" );
  663. // Copy the display name into the caller's buffer, and free it.
  664. wcscpy( wszDisplayName, wszReturnedDisplayName );
  665. bSuccess = TRUE;
  666. // ----
  667. // Exit
  668. // ----
  669. Exit:
  670. if( wszReturnedDisplayName )
  671. {
  672. CoTaskMemFree( wszReturnedDisplayName );
  673. wszReturnedDisplayName = NULL;
  674. }
  675. DisplayErrors( bSuccess, L"CMoniker::GetDisplayName()" );
  676. return( bSuccess );
  677. } // CMoniker::GetDisplayName()
  678. //+-------------------------------------------------------------
  679. //
  680. // Function: CMoniker::InitializeBindContext
  681. //
  682. // Synopsis: Create a new bind context, and store it
  683. // in a member pointer.
  684. //
  685. // Inputs: None.
  686. //
  687. // Output: TRUE if successful, FALSE otherwise.
  688. //
  689. // Effects: Updates m_pIBindCtx.
  690. //
  691. //+-------------------------------------------------------------
  692. BOOL CMoniker::InitializeBindContext( )
  693. {
  694. // ---------------
  695. // Local Variables
  696. // ---------------
  697. BOOL bSuccess = FALSE;
  698. // -----
  699. // Begin
  700. // -----
  701. m_hr = S_OK;
  702. // Release the old bind context if we have one.
  703. if( m_pIBindCtx )
  704. m_pIBindCtx->Release();
  705. // Create the new bind context.
  706. m_hr = CreateBindCtx( 0L, &m_pIBindCtx );
  707. EXIT_ON_FAILED( L"Failed CreateBindCtx()" );
  708. bSuccess = TRUE;
  709. // ----
  710. // Exit
  711. // ----
  712. Exit:
  713. DisplayErrors( bSuccess, L"CMoniker::InitializeBindContext()" );
  714. return( bSuccess );
  715. } // CMoniker::InitializeBindContext()
  716. //+----------------------------------------------------------------
  717. //
  718. // Function: CMoniker::GetTimeOfLastChange
  719. //
  720. // Synopsis: Request the time-of-last-change from our member
  721. // moniker.
  722. //
  723. // Inputs: A buffer into which to put the FILETIME.
  724. //
  725. // Output: TRUE if successful, FALSE otherwise.
  726. //
  727. // Effects: None.
  728. //
  729. //+----------------------------------------------------------------
  730. BOOL CMoniker::GetTimeOfLastChange( FILETIME* pft )
  731. {
  732. // ---------------
  733. // Local Variables
  734. // ---------------
  735. BOOL bSuccess = FALSE;
  736. // -----
  737. // Begin
  738. // -----
  739. m_hr = S_OK;
  740. // Validate our state.
  741. if( !m_pIMoniker )
  742. EXIT( L"Cannot GetTimeOfLastChange on a NULL moniker" );
  743. // Get the time from the moniker.
  744. m_hr = m_pIMoniker->GetTimeOfLastChange( m_pIBindCtx,
  745. NULL,
  746. pft );
  747. EXIT_ON_FAILED( L"Failed IMoniker::GetTimeOfLastChange()" );
  748. bSuccess = TRUE;
  749. // ----
  750. // Exit
  751. // ----
  752. Exit:
  753. DisplayErrors( bSuccess, L"CMoniker::GetTimeOfLastChange()" );
  754. return( bSuccess );
  755. } // CMoniker::GetTimeOfLastChange()
  756. //+------------------------------------------------------------------------
  757. //
  758. // Function: CMoniker::BindToStorage
  759. //
  760. // Synopsis: Bind our member moniker to its Structured Storage object.
  761. //
  762. // Inputs: None.
  763. //
  764. // Outputs: TRUE if successful, FALSE otherwise.
  765. //
  766. // Effects: None.
  767. //
  768. //+------------------------------------------------------------------------
  769. BOOL CMoniker::BindToStorage()
  770. {
  771. // ---------------
  772. // Local Variables
  773. // ---------------
  774. BOOL bSuccess = FALSE;
  775. BIND_OPTS2 bind_opts;
  776. bind_opts.cbStruct = sizeof( BIND_OPTS2 );
  777. // -----
  778. // Begin
  779. // -----
  780. m_hr = S_OK;
  781. // Validate our state.
  782. if( !m_pIMoniker )
  783. EXIT( L"Cannot GetTimeOfLastChange on a NULL moniker" );
  784. // Release the IStorage interface if we have one.
  785. if( m_pIStorage )
  786. {
  787. m_pIStorage->Release();
  788. m_pIStorage = NULL;
  789. }
  790. // Get the bind_opts and set the flags for StgOpenStorage.
  791. m_hr = m_pIBindCtx->GetBindOptions( (LPBIND_OPTS) &bind_opts );
  792. EXIT_ON_FAILED( L"Failed IBindCtx::GetBindOptions" );
  793. bind_opts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT;
  794. m_hr = m_pIBindCtx->SetBindOptions( (LPBIND_OPTS) &bind_opts );
  795. EXIT_ON_FAILED( L"Failed IBindCtx::SetBindOptions" );
  796. // Bind to the storage.
  797. m_hr = m_pIMoniker->BindToStorage( m_pIBindCtx,
  798. NULL,
  799. IID_IStorage,
  800. (void **) &m_pIStorage );
  801. EXIT_ON_FAILED( L"Failed IMoniker::BindToStorage()" );
  802. bSuccess = TRUE;
  803. // ----
  804. // Exit
  805. // ----
  806. Exit:
  807. // Release the Storage if we got it.
  808. if( m_pIStorage )
  809. {
  810. m_pIStorage->Release();
  811. m_pIStorage = NULL;
  812. }
  813. DisplayErrors( bSuccess, L"CMoniker::BindToStorage()" );
  814. return( bSuccess );
  815. } // CMoniker::BindToStorage()
  816. //+-------------------------------------------------------------------
  817. //
  818. // Function: CMoniker::BindToObject
  819. //
  820. // Synopsis: Bind to our member moniker's object.
  821. //
  822. // Inputs: None.
  823. //
  824. // Outputs: TRUE if successful, FALSE otherwise.
  825. //
  826. // Effects: None.
  827. //
  828. // Notes: Since the member moniker represents a storage with no
  829. // associated server, BindToObject will fail. We will
  830. // consider it a success if the failure is do to an
  831. // object-related problem, rather than a Storage-related
  832. // problem.
  833. //
  834. //+-------------------------------------------------------------------
  835. BOOL CMoniker::BindToObject()
  836. {
  837. // ---------------
  838. // Local Variables
  839. // ---------------
  840. BOOL bSuccess = FALSE;
  841. IUnknown* pUnk = NULL;
  842. // -----
  843. // Begin
  844. // -----
  845. m_hr = S_OK;
  846. // Validate our state.
  847. if( !m_pIMoniker )
  848. EXIT( L"Cannot bind to an object with a NULL moniker" );
  849. // Bind to the object.
  850. m_hr = m_pIMoniker->BindToObject( m_pIBindCtx,
  851. NULL,
  852. IID_IUnknown,
  853. (void **) &pUnk );
  854. // If the bind succeeded, or failed for a valid reason,
  855. // then return Success to the caller.
  856. if( SUCCEEDED( m_hr )
  857. ||
  858. ( m_hr = MK_E_INVALIDEXTENSION ) // No handler for ".tmp" files.
  859. )
  860. {
  861. bSuccess = TRUE;
  862. }
  863. else
  864. {
  865. EXIT( L"Failed BindToObject" );
  866. }
  867. // ----
  868. // Exit
  869. // ----
  870. Exit:
  871. // If we got an IUnknown interface on the Bind, release it.
  872. if( pUnk )
  873. {
  874. pUnk->Release();
  875. pUnk = NULL;
  876. }
  877. DisplayErrors( bSuccess, L"CMoniker::BindToObject()" );
  878. return( bSuccess );
  879. } // CMoniker::BindToObject()
  880. //+-------------------------------------------------------------------
  881. //
  882. // Function: CMoniker::GetTemporaryStorageTime
  883. //
  884. // Synopsis: Get the time from the link source file
  885. // (identified by m_wszTemporaryStorage).
  886. //
  887. // Inputs: A buffer in which to put the FILETIME structure.
  888. //
  889. // Outputs: TRUE if successful, FALSE otherwise.
  890. //
  891. // Effects: None.
  892. //
  893. //+-------------------------------------------------------------------
  894. BOOL CMoniker::GetTemporaryStorageTime( FILETIME * pft)
  895. {
  896. // ---------------
  897. // Local Variables
  898. // ---------------
  899. BOOL bSuccess = FALSE;
  900. HANDLE hFile = NULL;
  901. // -----
  902. // Begin
  903. // -----
  904. m_hr = NOERROR;
  905. // Get a handle to the file.
  906. hFile = CreateFile( m_wszTemporaryStorage, // File name
  907. GENERIC_READ, // Desired access
  908. FILE_SHARE_READ, // Share mode
  909. NULL, // Security attributes
  910. OPEN_EXISTING, // Creation distribution
  911. 0L, // Flags & Attributes
  912. NULL ); // hTemplateFile
  913. if( hFile == NULL )
  914. {
  915. m_hr = (HRESULT) GetLastError();
  916. EXIT( L"Failed call to CreateFile()" );
  917. }
  918. // Get the time on the file.
  919. if( !GetFileTime( hFile, // File to check
  920. NULL, // Create Time
  921. NULL, // Access Time
  922. pft ) // Write Time
  923. )
  924. {
  925. m_hr = (HRESULT) GetLastError();
  926. EXIT( L"Failed call to GetFileTime()" );
  927. }
  928. bSuccess = TRUE;
  929. // ----
  930. // Exit
  931. // ----
  932. Exit:
  933. // Close the file if we opened it.
  934. if( hFile )
  935. {
  936. CloseHandle( hFile );
  937. hFile = NULL;
  938. }
  939. DisplayErrors( bSuccess, L"CMoniker::GetTemporaryStorageTime()" );
  940. return( bSuccess );
  941. } // CMoniker::GetTemporaryStorageTime()
  942. //+------------------------------------------------------------------------
  943. //
  944. // Function: CMoniker::TouchTemporaryStorage
  945. //
  946. // Synopsis: Set the Access time on the link source file.
  947. //
  948. // Inputs: None.
  949. //
  950. // Output: TRUE if successful, FALSE otherwise.
  951. //
  952. // Effects: The link source file (identified by m_wszTemporaryStorage)
  953. // has its Access time set to the current time.
  954. //
  955. //+------------------------------------------------------------------------
  956. BOOL CMoniker::TouchTemporaryStorage( )
  957. {
  958. // ---------------
  959. // Local Variables
  960. // ---------------
  961. BOOL bSuccess = FALSE;
  962. HANDLE hFile = NULL;
  963. STATSTG statStorage;
  964. FILETIME ftNow;
  965. // -----
  966. // Begin
  967. // -----
  968. m_hr = NOERROR;
  969. // Open the root Storage.
  970. m_hr = StgOpenStorage( m_wszTemporaryStorage,
  971. NULL,
  972. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
  973. NULL,
  974. 0L,
  975. &m_pIStorage );
  976. EXIT_ON_FAILED( L"Failed StgOpenStorage()" );
  977. // Get the current time.
  978. m_hr = CoFileTimeNow( &ftNow );
  979. EXIT_ON_FAILED( L"Failed CoFileTimeNow()" );
  980. // Set the access time
  981. m_pIStorage->SetElementTimes( NULL, // Set the storage itself
  982. NULL, // Create time
  983. NULL, // Access time
  984. &ftNow );
  985. EXIT_ON_FAILED( L"Failed IStorage::SetTimes()" );
  986. bSuccess = TRUE;
  987. // ----
  988. // Exit
  989. // ----
  990. Exit:
  991. // If we got the storage, release it.
  992. if( m_pIStorage )
  993. {
  994. m_pIStorage->Release();
  995. m_pIStorage = NULL;
  996. }
  997. DisplayErrors( bSuccess, L"CMoniker::TouchTemporaryStorage()" );
  998. return( bSuccess );
  999. } // CMoniker::TouchTemporaryStorage()
  1000. #ifdef _FUTURE_
  1001. /*
  1002. BOOL CMoniker::OpenLinkTrackingRegistryKey()
  1003. {
  1004. BOOL bSuccess = FALSE;
  1005. DWORD dwDisposition = 0L;
  1006. long lResult = 0L;
  1007. m_hr = S_OK;
  1008. lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1009. OLETRACKING_KEY,
  1010. 0L,
  1011. KEY_ALL_ACCESS,
  1012. &m_hkeyLinkTracking
  1013. );
  1014. if( lResult != ERROR_SUCCESS
  1015. &&
  1016. lResult != ERROR_FILE_NOT_FOUND
  1017. )
  1018. {
  1019. m_hr = (HRESULT) lResult;
  1020. EXIT( L"Failed RegOpenKeyEx()" );
  1021. }
  1022. bSuccess = TRUE;
  1023. Exit:
  1024. DisplayErrors( bSuccess, L"CMoniker::OpenLinkTrackingRegistryKey()" );
  1025. return( bSuccess );
  1026. } // CMoniker::OpenLinkTrackingRegistryKey()
  1027. BOOL CMoniker::CreateLinkTrackingRegistryKey()
  1028. {
  1029. BOOL bSuccess = FALSE;
  1030. HKEY hkey = NULL;
  1031. DWORD dwDisposition = 0L;
  1032. long lResult = 0L;
  1033. m_hr = S_OK;
  1034. if( m_hkeyLinkTracking )
  1035. CloseLinkTrackingRegistryKey();
  1036. lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  1037. OLETRACKING_KEY,
  1038. 0L,
  1039. NULL,
  1040. REG_OPTION_NON_VOLATILE,
  1041. KEY_ALL_ACCESS,
  1042. NULL,
  1043. &m_hkeyLinkTracking,
  1044. &dwDisposition
  1045. );
  1046. if( lResult != ERROR_SUCCESS )
  1047. {
  1048. m_hr = (HRESULT) lResult;
  1049. EXIT( L"Failed RegCreateKeyEx()" );
  1050. }
  1051. bSuccess = TRUE;
  1052. Exit:
  1053. DisplayErrors( bSuccess, L"CMoniker::CreateLinkTrackingRegistryKey()" );
  1054. return( bSuccess );
  1055. } // CMoniker::CreateLinkTrackingRegistryKey()
  1056. BOOL CMoniker::CloseLinkTrackingRegistryKey()
  1057. {
  1058. m_hr = S_OK;
  1059. if( m_hkeyLinkTracking )
  1060. RegCloseKey( m_hkeyLinkTracking );
  1061. m_hkeyLinkTracking = NULL;
  1062. return TRUE;
  1063. } // CMoniker::CloseLinkTrackingRegistryKey()
  1064. BOOL CMoniker::SaveRegistryTrackFlags()
  1065. {
  1066. BOOL bSuccess = FALSE;
  1067. long lResult = 0L;
  1068. DWORD dwType = 0L;
  1069. DWORD dwcbData = sizeof( m_dwTrackFlags );
  1070. m_hr = S_OK;
  1071. if( !OpenLinkTrackingRegistryKey() )
  1072. EXIT( L"Could not open the registry" );
  1073. lResult = RegQueryValueEx( m_hkeyLinkTracking,
  1074. OLETRACKING_FILEMONIKER_VALUE,
  1075. NULL,
  1076. &dwType,
  1077. (LPBYTE) &m_dwTrackFlags,
  1078. &dwcbData );
  1079. if( lResult != ERROR_SUCCESS )
  1080. {
  1081. CloseLinkTrackingRegistryKey();
  1082. if( lResult != ERROR_FILE_NOT_FOUND )
  1083. {
  1084. m_hr = (HRESULT) lResult;
  1085. EXIT( L"Failed RegQueryValueEx()" );
  1086. }
  1087. }
  1088. bSuccess = TRUE;
  1089. Exit:
  1090. DisplayErrors( bSuccess, L"CMoniker::SaveRegistryTrackFlags()" );
  1091. return( bSuccess );
  1092. } // CMoniker::SaveRegistryTrackFlags()
  1093. BOOL CMoniker::DeleteRegistryTrackFlags()
  1094. {
  1095. BOOL bSuccess = FALSE;
  1096. long lResult = 0L;
  1097. DWORD dwType = 0L;
  1098. DWORD dwcbData = sizeof( m_dwTrackFlags );
  1099. m_hr = S_OK;
  1100. if( !CreateLinkTrackingRegistryKey() )
  1101. EXIT( L"Could not open the registry" );
  1102. lResult = RegDeleteValue( m_hkeyLinkTracking,
  1103. OLETRACKING_FILEMONIKER_VALUE );
  1104. if( lResult != ERROR_SUCCESS
  1105. &&
  1106. lResult != ERROR_FILE_NOT_FOUND
  1107. )
  1108. {
  1109. if( lResult != ERROR_FILE_NOT_FOUND )
  1110. {
  1111. m_hr = (HRESULT) lResult;
  1112. EXIT( L"Failed RegDeleteValue()" );
  1113. }
  1114. }
  1115. bSuccess = TRUE;
  1116. Exit:
  1117. CloseLinkTrackingRegistryKey();
  1118. DisplayErrors( bSuccess, L"CMoniker::DeleteRegistryTrackFlags()" );
  1119. return( bSuccess );
  1120. } // CMoniker::DeleteRegistryTrackFlags()
  1121. BOOL CMoniker::RestoreRegistryTrackFlags()
  1122. {
  1123. BOOL bSuccess = FALSE;
  1124. long lResult = 0L;
  1125. m_hr = S_OK;
  1126. // If the registry key doesn't exist, then there's no flags
  1127. // to restore.
  1128. if( m_hkeyLinkTracking )
  1129. {
  1130. lResult = RegSetValueEx( m_hkeyLinkTracking,
  1131. OLETRACKING_FILEMONIKER_VALUE,
  1132. 0L,
  1133. REG_DWORD,
  1134. (LPBYTE) &m_dwTrackFlags,
  1135. sizeof( m_dwTrackFlags )
  1136. );
  1137. if( lResult != ERROR_SUCCESS )
  1138. {
  1139. m_hr = (HRESULT) lResult;
  1140. EXIT( L"Failed RegSetValueEx()" );
  1141. }
  1142. CloseLinkTrackingRegistryKey();
  1143. }
  1144. bSuccess = TRUE;
  1145. Exit:
  1146. DisplayErrors( bSuccess, L"CMoniker::RestoreRegistryTrackFlags()" );
  1147. return( bSuccess );
  1148. } // CMoniker::RestoreRegistryTrackFlags()
  1149. CMoniker::SetTrackFlagsInRegistry( DWORD dwTrackFlags )
  1150. {
  1151. BOOL bSuccess = FALSE;
  1152. long lResult = 0L;
  1153. HKEY hkey = NULL;
  1154. m_hr = S_OK;
  1155. if( !CreateLinkTrackingRegistryKey() )
  1156. EXIT( L"Could not create registry key" );
  1157. lResult = RegSetValueEx( m_hkeyLinkTracking,
  1158. OLETRACKING_FILEMONIKER_VALUE,
  1159. 0L,
  1160. REG_DWORD,
  1161. (LPBYTE) &dwTrackFlags,
  1162. sizeof( dwTrackFlags )
  1163. );
  1164. if( lResult != ERROR_SUCCESS )
  1165. {
  1166. m_hr = (HRESULT) lResult;
  1167. EXIT( L"Failed RegSetValueEx()" );
  1168. }
  1169. bSuccess = TRUE;
  1170. Exit:
  1171. DisplayErrors( bSuccess, L"CMoniker::SetTrackFlagsInRegistry()" );
  1172. return( bSuccess );
  1173. } // CMoniker::SetTrackFlagsInRegistry()
  1174. BOOL CMoniker::CreateFileMoniker()
  1175. {
  1176. BOOL bSuccess = FALSE;
  1177. m_hr = S_OK;
  1178. // Free any existing IMoniker.
  1179. if( m_pIMoniker )
  1180. {
  1181. m_pIMoniker->Release();
  1182. m_pIMoniker = NULL;
  1183. }
  1184. // Create a root storage.
  1185. if( !CreateTemporaryStorage() )
  1186. EXIT( L"Could not create a temporary storage" );
  1187. // Create a default File Moniker on that root storage.
  1188. m_hr = ::CreateFileMoniker( m_wszTemporaryStorage, &m_pIMoniker );
  1189. EXIT_ON_FAILED( L"Failed CreateFileMoniker" );
  1190. bSuccess = TRUE;
  1191. Exit:
  1192. DisplayErrors( bSuccess, L"CMoniker::CreateFileMoniker" );
  1193. return( bSuccess );
  1194. } // CMoniker::CreateFileMoniker()
  1195. */
  1196. #endif // _FUTURE_