summaryrefslogtreecommitdiffstats
path: root/private/oleutest/cfmex/cmoniker.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleutest/cfmex/cmoniker.cxx')
-rw-r--r--private/oleutest/cfmex/cmoniker.cxx1684
1 files changed, 1684 insertions, 0 deletions
diff --git a/private/oleutest/cfmex/cmoniker.cxx b/private/oleutest/cfmex/cmoniker.cxx
new file mode 100644
index 000000000..7a9c555a7
--- /dev/null
+++ b/private/oleutest/cfmex/cmoniker.cxx
@@ -0,0 +1,1684 @@
+
+//+=======================================================================
+//
+// File: CMoniker.cxx
+//
+// Purpose: Define the CMoniker class.
+//
+// This class provides for all handling of monikers in
+// the CreateFileMonikerEx DRT. Not only does it maintain
+// a file moniker, it also maintains the represented link
+// source file, and a bind context.
+//
+//+=======================================================================
+
+// --------
+// Includes
+// --------
+
+#define _DCOM_ // Allow DCOM extensions (e.g., CoInitializeEx).
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <wtypes.h>
+#include <oaidl.h>
+#include <dsys.h>
+#include <olecairo.h>
+#include "CFMEx.hxx"
+#include "CMoniker.hxx"
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMoniker::CMoniker
+//
+// Synopsis: Simply initialize all member variables.
+//
+// Inputs: None.
+//
+// Outputs: N/A
+//
+// Effects: Members are defaulted/initialized.
+//
+//+-------------------------------------------------------------------------
+
+
+CMoniker::CMoniker()
+{
+ *m_wszSystemTempPath = L'\0';
+ *m_wszTemporaryStorage = L'\0';
+ m_pIMoniker = NULL;
+ m_pIBindCtx = NULL;
+ m_pIStorage = NULL;
+ *m_wszErrorMessage = L'\0';
+ m_dwTrackFlags = 0L;
+ m_hkeyLinkTracking = NULL;
+ m_hr = 0L;
+ m_bSuppressErrorMessages = FALSE;
+ m_pcDirectoryOriginal = NULL;
+ m_pcDirectoryFinal = NULL;
+
+ return;
+
+} // CMoniker::CMoniker()
+
+
+//+--------------------------------------------------------------------------
+//
+// Function: CMoniker::~CMoniker
+//
+// Synopsis: Release any COM objects.
+//
+// Inputs: N/A
+//
+// Outputs: N/A
+//
+// Effects: All COM objects are released.
+//
+//+--------------------------------------------------------------------------
+
+
+CMoniker::~CMoniker()
+{
+ if( m_pIMoniker )
+ {
+ m_pIMoniker->Release();
+ m_pIMoniker = NULL;
+ }
+
+ if( m_pIBindCtx )
+ {
+ m_pIBindCtx->Release();
+ m_pIBindCtx = NULL;
+ }
+
+ if( m_pIStorage )
+ {
+ m_pIStorage->Release();
+ m_pIStorage = NULL;
+ }
+
+ return;
+
+} // CMoniker::~CMoniker()
+
+
+//+-----------------------------------------------------------------------
+//
+// Function: CMoniker::Initialize
+//
+// Synopsis: Keep pointers to the CDirectory objects passed in.
+//
+// Inputs: A CDirectory object for the original link source file location
+// A CDirectory object for the final location
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: The member CDirectory objects are set.
+//
+//+-----------------------------------------------------------------------
+
+
+BOOL CMoniker::Initialize( const CDirectory& cDirectoryOriginal,
+ const CDirectory& cDirectoryFinal )
+{
+ m_hr = S_OK;
+
+ m_pcDirectoryOriginal = &cDirectoryOriginal;
+ m_pcDirectoryFinal = &cDirectoryFinal;
+
+ return( TRUE ); // Success
+
+} // CMoniker::Initialize()
+
+
+//+-----------------------------------------------------------------------------
+//
+// Function: CMoniker::CreateFileMonikerEx
+//
+// Synopsis: Create a tracking file moniker. But before doing so, initialize
+// the Bind Context, and create a link source file.
+//
+// Inputs: Track Flags (from the TRACK_FLAGS defines)
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: The member bind context is initialized, and a link
+// source file is created.
+//
+//+-----------------------------------------------------------------------------
+
+
+BOOL CMoniker::CreateFileMonikerEx( DWORD dwTrackFlags )
+{
+
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ // Assume failure
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ // Initialize the error code.
+
+ m_hr = S_OK;
+
+ // Free any existing IMoniker.
+
+ if( m_pIMoniker )
+ {
+ m_pIMoniker->Release();
+ m_pIMoniker = NULL;
+ }
+
+ // Initialize the bind context.
+
+ if( !InitializeBindContext() )
+ EXIT( L"Could not initialize the bind context" );
+
+ // Create a root storage for use as a link source.
+
+ if( !CreateTemporaryStorage() )
+ EXIT( L"Could not create temporary Storage" );
+
+ // Create a tracking File Moniker on that root storage.
+
+ m_hr = ::CreateFileMonikerEx( dwTrackFlags, m_wszTemporaryStorage, &m_pIMoniker );
+ EXIT_ON_FAILED( L"Failed CreateFileMonikerEx" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::CreateFileMonikerEx" );
+ return( bSuccess );
+
+} // CMoniker::CreateFileMonikerEx()
+
+
+//+---------------------------------------------------------------------
+//
+// Function: CMoniker::SaveDeleteLoad
+//
+// Synopsis: This function exercises a moniker's IPersistStream interface.
+// It creates saves the member moniker's persistent state to
+// a stream, deletes the moniker, and then re-creates it
+// using CreateFileMoniker (no Ex, so it's not a tracking
+// file moniker). It then re-loads the original moniker's
+// persistent state.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: The member moniker is deleted, re-created, and re-loaded.
+//
+//+---------------------------------------------------------------------
+
+
+BOOL CMoniker::SaveDeleteLoad()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ // Assume failure
+ BOOL bSuccess = FALSE;
+ HRESULT hr = E_FAIL;
+
+ IStream* pStream = NULL;
+ IPersistStream* pIPersistStream = NULL;
+ LARGE_INTEGER li;
+ ULARGE_INTEGER uli;
+
+ // -----
+ // Begin
+ // -----
+
+ // Initialize the error code.
+
+ m_hr = S_OK;
+
+ // Verify that we have a member moniker.
+
+ if( !m_pIMoniker )
+ EXIT( L"Attempt to run SaveDeleteLoad test without an existing file moniker" );
+
+
+ // ------------------------
+ // Save the moniker's state
+ // ------------------------
+
+ // Get the moniker's IPersistStream interface
+
+ m_hr = m_pIMoniker->QueryInterface( IID_IPersistStream, (void **) &pIPersistStream );
+ EXIT_ON_FAILED( L"Failed 1st IMoniker::QueryInterface(IPersistStream)" );
+
+ // Create a stream
+
+ hr = CreateStreamOnHGlobal( NULL, // Auto alloc
+ TRUE, // Delete on release
+ &pStream );
+ EXIT_ON_FAILED( L"Failed CreateStreamOnHGlobal()" );
+
+ // Save the moniker's state to this stream.
+
+ hr = pIPersistStream->Save( pStream, TRUE /* Clear dirty*/ );
+ EXIT_ON_FAILED( L"Failed IPersistStream::Save()" );
+
+ // ------------------
+ // Delete the moniker
+ // ------------------
+
+ // Release all interfaces for the moniker.
+
+ m_pIMoniker->Release();
+ pIPersistStream->Release();
+
+ m_pIMoniker = NULL;
+ pIPersistStream = NULL;
+
+ // --------------------
+ // Create a new moniker
+ // --------------------
+
+ // Create a new moniker, using the non-Ex version of the function.
+
+ m_hr = ::CreateFileMoniker( m_wszTemporaryStorage, &m_pIMoniker );
+ EXIT_ON_FAILED( L"Failed CreateFileMoniker()" );
+
+ // --------------------
+ // Load the new moniker
+ // --------------------
+
+ // Get the IPersisStream interface
+
+ m_hr = m_pIMoniker->QueryInterface( IID_IPersistStream, (void **) &pIPersistStream );
+ EXIT_ON_FAILED( L"Failed 2nd IMoniker::QueryInterface(IPersistStream)" );
+
+ // Re-seek the stream to the beginning.
+
+ li.LowPart = li.HighPart = 0L;
+ hr = pStream->Seek( li, STREAM_SEEK_SET, &uli );
+ EXIT_ON_FAILED( L"Failed IStream::Seek()" );
+ if( uli.LowPart || uli.HighPart ) EXIT( L"Incorrect IStream::Seek()" );
+
+ // Re-load the moniker from the stream.
+
+ m_hr = pIPersistStream->Load( pStream );
+ EXIT_ON_FAILED( L"Failed IPersistStream::Load()" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Clean up the stream and the IPersistStream interface.
+
+ if( pStream )
+ pStream->Release;
+
+ if( pIPersistStream )
+ pIPersistStream->Release();
+
+
+ DisplayErrors( bSuccess, L"CMoniker::SaveDeleteLoad()" );
+ return( bSuccess );
+
+} // CMoniker::SaveDeleteLoad()
+
+
+//+------------------------------------------------------------------
+//
+// Function: CMoniker::ComposeWith
+//
+// Synopsis: Compose a tracking moniker with a non-tracking moniker
+// on the right. (The resulting moniker should be tracking,
+// but this is not relevant to this function; that is, whether
+// or not the composed moniker is tracking, this function will
+// succeed.)
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: The member moniker is deleted, then recreated.
+//
+//+------------------------------------------------------------------
+
+BOOL CMoniker::ComposeWith()
+{
+
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ IMoniker* pmkrFirst = NULL;
+ IMoniker* pmkrSecond = NULL;
+ HRESULT hr = E_FAIL;
+
+ WCHAR wszDirectoryName[ MAX_PATH + sizeof( L'\0' ) ];
+ WCHAR* wszFileName = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ // Initiailize the error code.
+
+ m_hr = S_OK;
+
+ // If we have a moniker already, delete it.
+
+ if( m_pIMoniker )
+ {
+ m_pIMoniker->Release();
+ m_pIMoniker = NULL;
+ }
+
+ // Verify we already have a link source file created.
+
+ if( !wcslen( m_wszTemporaryStorage ) )
+ EXIT( L"Attempt to use ComposeWith without first creating a link source.\n" );
+
+ // -----------------------------------------------
+ // Create a tracking and non-tracking file moniker
+ // -----------------------------------------------
+
+ // Parse the storage's filename into a path and a file ...
+ // for example, "C:\Temp\file.tmp" would become
+ // "C:\Temp" and "file.tmp".
+ //
+ // First, make a copy of the storage's complete path name,
+ // then replace the last '\\' with a '\0', thus creating two
+ // strings.
+
+ wcscpy( wszDirectoryName, m_wszTemporaryStorage );
+ wszFileName = wcsrchr( wszDirectoryName, L'\\' );
+ *wszFileName = L'\0';
+ wszFileName++;
+
+ // Create a tracking file moniker using the directory name.
+
+ m_hr = ::CreateFileMonikerEx( 0L, wszDirectoryName, &pmkrFirst );
+ EXIT_ON_FAILED( L"Failed 1st CreateFileMoniker()" );
+
+ // Create a non-tracking file moniker using the file name.
+
+ m_hr = ::CreateFileMoniker( wszFileName, &pmkrSecond );
+ EXIT_ON_FAILED( L"Failed 2nd CreateFileMoniker()" );
+
+ // -------
+ // Compose
+ // -------
+
+ // Compose the directory name moniker (on the left) with the file name moniker
+ // (on the right). Put the result in the member moniker.
+
+ m_hr = pmkrFirst->ComposeWith( pmkrSecond, TRUE, &m_pIMoniker );
+ EXIT_ON_FAILED( L"Failed IMoniker::ComposeWith" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Clean up the intermediary monikers.
+
+ if( pmkrFirst )
+ pmkrFirst->Release();
+
+ if( pmkrSecond )
+ pmkrSecond->Release();
+
+ DisplayErrors( bSuccess, L"CMoniker::ComposeWith()" );
+ return( bSuccess );
+
+} // CMoniker::ComposeWith()
+
+
+//+--------------------------------------------------------------------
+//
+// Function: CMoniker::CreateTemporaryStorage
+//
+// Synopsis: This function creates a Structured Storage
+// in the directory identified by m_cDirectoryOriginal.
+// The name of the file is randomly generated by the system,
+// but begins with "MKR" and has the extension ".tmp".
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: Stores the Structure Storage's name in
+// m_wszTemporaryStorageName, and releases m_pIStorage if
+// it is currently set.
+//
+//+--------------------------------------------------------------------
+
+
+BOOL CMoniker::CreateTemporaryStorage()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ DWORD dwError = 0L;
+ UINT nError = 0;
+
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Delete any existing storage.
+
+ if( wcslen( m_wszTemporaryStorage ))
+ {
+ if( !DeleteTemporaryStorage() )
+ EXIT( L"Could not delete the existing temporary storage" );
+ }
+
+ // Generate a temporary filename.
+
+ nError = GetTempFileName( m_pcDirectoryOriginal->GetDirectoryName(),
+ L"MKR", // Prefix string.
+ 0, // Generate random number,
+ m_wszTemporaryStorage );
+ if( nError == 0 )
+ {
+ m_hr = (HRESULT) GetLastError();
+ EXIT( L"Failed GetTempFileName()" );
+ }
+
+ // Create a root Storage.
+
+ m_hr = StgCreateDocfile( m_wszTemporaryStorage,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
+ 0L, // Reserved
+ &m_pIStorage );
+ EXIT_ON_FAILED( L"Failed StgCreateDocfile()" );
+
+
+ // Release the storage.
+
+ m_pIStorage->Release();
+ m_pIStorage = NULL;
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+
+ DisplayErrors( bSuccess, L"CMoniker::CreateTemporaryStorage()" );
+ return( bSuccess );
+
+} // CMoniker::CreateTemporaryStorage()
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMoniker::RenameTemporaryStorage
+//
+// Synopsis: Rename the link source file (who's name is in m_wszTemporaryStorage)
+// to the m_cDirectoryFinal directory, with a new name.
+// The current name is "MKR#.tmp" (where "#" is a random number
+// generated by the system), and the new name is "RKM#.tmp" (where
+// "#" is the same random number). (We must rename the base file
+// name, rather than its extension, because otherwise the default
+// link-tracking would fail (it would only score the renamed file
+// a 32 - by matching the file extension the score is 40.)
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: The link source file is renamed, and it's new name is
+// put into m_wszTemporaryStorage.
+//
+//+-------------------------------------------------------------------------
+
+
+BOOL CMoniker::RenameTemporaryStorage()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ int nError = 0;
+
+ WCHAR wszNewName[ MAX_PATH + sizeof( L'\0' ) ];
+ WCHAR* wszOldFileName;
+ WCHAR wszNewFileName[ MAX_PATH + sizeof( L'\0' ) ];
+
+ char szOldName[ MAX_PATH + sizeof( L'\0' ) ];
+ char szNewName[ MAX_PATH + sizeof( L'\0' ) ];
+
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Verify that we already have a link source created.
+
+ if( !wcslen( m_wszTemporaryStorage ))
+ EXIT( L"No temporary storage to rename." );
+
+ // Locate the file name within the complete path.
+ // (E.g., find the "foo.txt" in "C:\TEMP\foot.txt".)
+
+ wszOldFileName = wcsrchr( m_wszTemporaryStorage, L'\\' );
+ if( !wszOldFileName )
+ EXIT( L"Could not extract old file name from temporary storage name\n" );
+ wszOldFileName++; // Get past the '\\'
+
+ // Generate the new file name (change "MKR" to "RKM").
+
+ wcscpy( wszNewFileName, wszOldFileName );
+
+ wszNewFileName[0] = L'R';
+ wszNewFileName[1] = L'K';
+ wszNewFileName[2] = L'M';
+
+ // Generate the complete path spec of the new file.
+
+ wcscpy( wszNewName, m_pcDirectoryFinal->GetDirectoryName() );
+ wcscat( wszNewName, wszNewFileName );
+
+
+ // Convert the new and old file names to ANSI.
+
+ if( m_hr = UnicodeToAnsi( m_wszTemporaryStorage, szOldName, sizeof( szOldName )) )
+ {
+ EXIT( L"Could not convert convert Unicode to Ansi for old name" );
+ }
+
+ if( m_hr = UnicodeToAnsi( wszNewName, szNewName, sizeof( szNewName )) )
+ {
+ EXIT( L"Could not convert convert Unicode to Ansi for new name" );
+ }
+
+
+ // Rename the file.
+
+ nError = rename( szOldName, szNewName );
+ if( nError )
+ {
+ m_hr = (HRESULT) errno;
+ EXIT( L"Failed rename()" );
+ }
+
+ // Record the new name.
+
+ wcscpy( m_wszTemporaryStorage, wszNewName );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::RenameTemporaryStorage()" );
+ return( bSuccess );
+
+} // CMoniker::RenameTemporaryStorage()
+
+
+//+--------------------------------------------------------------------
+//
+// Function: CMoniker::DeleteTemporaryStorage
+//
+// Synopsis: Delete the temporary storage that this object uses
+// as a link source for the moniker. The name of the
+// storage is in m_wszTemporaryStorage.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: The link source file is deleted, and m_wszTemporaryStorage
+// is set to a NULL string.
+//
+//+--------------------------------------------------------------------
+
+
+BOOL CMoniker::DeleteTemporaryStorage()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ int nError = 0;
+ CHAR szTemporaryStorage[ MAX_PATH + sizeof( '\0' ) ];
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Don't do anything if we have no file (don't report an
+ // error either; the caller wants the file deleted, and it's
+ // already not there).
+
+ if( wcslen( m_wszTemporaryStorage ))
+ {
+
+ // Get the file name in ANSI.
+
+ if( m_hr = UnicodeToAnsi( m_wszTemporaryStorage, szTemporaryStorage, sizeof( szTemporaryStorage )))
+ EXIT( L"Could not convert unicode path to ANSI path" );
+
+ // Delete the file.
+
+ nError = unlink( szTemporaryStorage );
+ if( nError )
+ {
+ m_hr = (HRESULT) errno;
+ EXIT( L"Failed unlink()" );
+ }
+
+ // Clear the file name.
+
+ wcscpy( m_wszTemporaryStorage, L"" );
+ }
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::DeleteTemporaryStorage()" );
+ return( bSuccess );
+
+} // CMoniker::DeleteTemporaryStorage()
+
+
+
+
+//+-----------------------------------------------------------------
+//
+// Function: CMoniker::Reduce
+//
+// Synopsis: Perform a IMoniker::Reduce on the member moniker.
+//
+// Inputs: - Number of ticks until the deadline for completion of
+// the operation.
+// - A buffer into which to put the reduced IMoniker*
+// (may be NULL).
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+-----------------------------------------------------------------
+
+
+BOOL CMoniker::Reduce( DWORD dwDelay, IMoniker** ppmkReturn )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ IMoniker* pmkReduced = NULL;
+ BIND_OPTS2 bind_opts;
+ bind_opts.cbStruct = sizeof( BIND_OPTS2 );
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ // Initialize the return buffer, if extant.
+
+ if( ppmkReturn )
+ *ppmkReturn = NULL;
+
+ // Validate our state.
+
+ if( !m_pIMoniker )
+ EXIT( L"No moniker exists to be reduced" );
+
+ // ----------------
+ // Set the deadline
+ // ----------------
+
+ // Get the BIND_OPTS from the bind context.
+
+ m_hr = m_pIBindCtx->GetBindOptions( (LPBIND_OPTS) &bind_opts );
+ EXIT_ON_FAILED( L"Failed IBindCtx::GetBindOptions" );
+
+ // Determine what the tick count of the deadline is.
+
+ if( dwDelay == INFINITE )
+ {
+ bind_opts.dwTickCountDeadline = 0;
+ }
+ else
+ {
+ bind_opts.dwTickCountDeadline = GetTickCount() + dwDelay;
+
+ // Make sure the resulting tick count is not 0 (indicating no
+ // deadline).
+
+ if( bind_opts.dwTickCountDeadline == 0 )
+ bind_opts.dwTickCountDeadline++;
+ }
+
+ // Put the resulting BIND_OPTS back into the bind context.
+
+ m_hr = m_pIBindCtx->SetBindOptions( (LPBIND_OPTS) &bind_opts );
+ EXIT_ON_FAILED( L"Failed IBindCtx::SetBindOptions" );
+
+
+ // ------------------
+ // Reduce the Moniker
+ // ------------------
+
+ m_hr = m_pIMoniker->Reduce( m_pIBindCtx,
+ MKRREDUCE_ALL,
+ NULL,
+ &pmkReduced );
+ EXIT_ON_FAILED( L"Failed IMoniker::Reduce" );
+
+ // Return the reduced moniker to the caller (if so requested).
+
+ if( ppmkReturn )
+ {
+ // Transfer responsibility for the release to the caller.
+ *ppmkReturn = pmkReduced;
+ pmkReduced = NULL;
+ }
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::Reduce()" );
+
+ if( pmkReduced )
+ pmkReduced->Release();
+
+ return( bSuccess );
+
+} // CMoniker::Reduce()
+
+
+
+//+----------------------------------------------------------------------
+//
+// Function: CMoniker::GetDisplayName
+//
+// Synopsis: Get the moniker's display name.
+//
+// Inputs: A Unicode buffer for the display name, and (optionally)
+// a moniker from which to get the display name. If such
+// a moniker is not provided by the caller, then the member
+// moniker is used.
+//
+// The unicode buffer must be long enough for MAX_PATH characters
+// and a terminating NULL.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+----------------------------------------------------------------------
+
+
+BOOL CMoniker::GetDisplayName( WCHAR * wszDisplayName, IMoniker* pmnkCaller )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ WCHAR* wszReturnedDisplayName = NULL;
+ IMoniker* pmnk = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = NOERROR;
+
+ // Determine which moniker to use, the caller-specified one or
+ // the member one.
+
+ if( pmnkCaller != NULL )
+ pmnk = pmnkCaller;
+ else
+ pmnk = m_pIMoniker;
+
+ if( !pmnk )
+ EXIT( L"Attempt to GetDisplayName on NULL moniker" );
+
+ // Get the display name from the moniker.
+
+ m_hr = pmnk->GetDisplayName( m_pIBindCtx,
+ NULL,
+ &wszReturnedDisplayName );
+ EXIT_ON_FAILED( L"Failed IMoniker::GetDisplayName()" );
+
+ if( wcslen( wszReturnedDisplayName ) > MAX_UNICODE_PATH )
+ EXIT( L"IMoniker::GetDisplayName() returned a path which was too long" );
+
+ // Copy the display name into the caller's buffer, and free it.
+
+ wcscpy( wszDisplayName, wszReturnedDisplayName );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( wszReturnedDisplayName )
+ {
+ CoTaskMemFree( wszReturnedDisplayName );
+ wszReturnedDisplayName = NULL;
+ }
+
+ DisplayErrors( bSuccess, L"CMoniker::GetDisplayName()" );
+ return( bSuccess );
+
+} // CMoniker::GetDisplayName()
+
+
+//+-------------------------------------------------------------
+//
+// Function: CMoniker::InitializeBindContext
+//
+// Synopsis: Create a new bind context, and store it
+// in a member pointer.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: Updates m_pIBindCtx.
+//
+//+-------------------------------------------------------------
+
+
+
+BOOL CMoniker::InitializeBindContext( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Release the old bind context if we have one.
+
+ if( m_pIBindCtx )
+ m_pIBindCtx->Release();
+
+ // Create the new bind context.
+
+ m_hr = CreateBindCtx( 0L, &m_pIBindCtx );
+ EXIT_ON_FAILED( L"Failed CreateBindCtx()" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::InitializeBindContext()" );
+ return( bSuccess );
+
+} // CMoniker::InitializeBindContext()
+
+
+//+----------------------------------------------------------------
+//
+// Function: CMoniker::GetTimeOfLastChange
+//
+// Synopsis: Request the time-of-last-change from our member
+// moniker.
+//
+// Inputs: A buffer into which to put the FILETIME.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+----------------------------------------------------------------
+
+
+BOOL CMoniker::GetTimeOfLastChange( FILETIME* pft )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Validate our state.
+
+ if( !m_pIMoniker )
+ EXIT( L"Cannot GetTimeOfLastChange on a NULL moniker" );
+
+ // Get the time from the moniker.
+
+ m_hr = m_pIMoniker->GetTimeOfLastChange( m_pIBindCtx,
+ NULL,
+ pft );
+ EXIT_ON_FAILED( L"Failed IMoniker::GetTimeOfLastChange()" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::GetTimeOfLastChange()" );
+ return( bSuccess );
+
+} // CMoniker::GetTimeOfLastChange()
+
+
+
+//+------------------------------------------------------------------------
+//
+// Function: CMoniker::BindToStorage
+//
+// Synopsis: Bind our member moniker to its Structured Storage object.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+------------------------------------------------------------------------
+
+
+BOOL CMoniker::BindToStorage()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ BIND_OPTS2 bind_opts;
+ bind_opts.cbStruct = sizeof( BIND_OPTS2 );
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Validate our state.
+
+ if( !m_pIMoniker )
+ EXIT( L"Cannot GetTimeOfLastChange on a NULL moniker" );
+
+ // Release the IStorage interface if we have one.
+
+ if( m_pIStorage )
+ {
+ m_pIStorage->Release();
+ m_pIStorage = NULL;
+ }
+
+ // Get the bind_opts and set the flags for StgOpenStorage.
+
+ m_hr = m_pIBindCtx->GetBindOptions( (LPBIND_OPTS) &bind_opts );
+ EXIT_ON_FAILED( L"Failed IBindCtx::GetBindOptions" );
+
+ bind_opts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT;
+
+ m_hr = m_pIBindCtx->SetBindOptions( (LPBIND_OPTS) &bind_opts );
+ EXIT_ON_FAILED( L"Failed IBindCtx::SetBindOptions" );
+
+
+ // Bind to the storage.
+
+ m_hr = m_pIMoniker->BindToStorage( m_pIBindCtx,
+ NULL,
+ IID_IStorage,
+ (void **) &m_pIStorage );
+ EXIT_ON_FAILED( L"Failed IMoniker::BindToStorage()" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Release the Storage if we got it.
+
+ if( m_pIStorage )
+ {
+ m_pIStorage->Release();
+ m_pIStorage = NULL;
+ }
+
+ DisplayErrors( bSuccess, L"CMoniker::BindToStorage()" );
+ return( bSuccess );
+
+} // CMoniker::BindToStorage()
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CMoniker::BindToObject
+//
+// Synopsis: Bind to our member moniker's object.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+// Notes: Since the member moniker represents a storage with no
+// associated server, BindToObject will fail. We will
+// consider it a success if the failure is do to an
+// object-related problem, rather than a Storage-related
+// problem.
+//
+//+-------------------------------------------------------------------
+
+BOOL CMoniker::BindToObject()
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ IUnknown* pUnk = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = S_OK;
+
+ // Validate our state.
+
+ if( !m_pIMoniker )
+ EXIT( L"Cannot bind to an object with a NULL moniker" );
+
+ // Bind to the object.
+
+ m_hr = m_pIMoniker->BindToObject( m_pIBindCtx,
+ NULL,
+ IID_IUnknown,
+ (void **) &pUnk );
+
+ // If the bind succeeded, or failed for a valid reason,
+ // then return Success to the caller.
+
+ if( SUCCEEDED( m_hr )
+ ||
+ ( m_hr = MK_E_INVALIDEXTENSION ) // No handler for ".tmp" files.
+ )
+ {
+ bSuccess = TRUE;
+ }
+ else
+ {
+ EXIT( L"Failed BindToObject" );
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we got an IUnknown interface on the Bind, release it.
+
+ if( pUnk )
+ {
+ pUnk->Release();
+ pUnk = NULL;
+ }
+
+ DisplayErrors( bSuccess, L"CMoniker::BindToObject()" );
+ return( bSuccess );
+
+} // CMoniker::BindToObject()
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CMoniker::GetTemporaryStorageTime
+//
+// Synopsis: Get the time from the link source file
+// (identified by m_wszTemporaryStorage).
+//
+// Inputs: A buffer in which to put the FILETIME structure.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+-------------------------------------------------------------------
+
+
+BOOL CMoniker::GetTemporaryStorageTime( FILETIME * pft)
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ HANDLE hFile = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = NOERROR;
+
+ // Get a handle to the file.
+
+ hFile = CreateFile( m_wszTemporaryStorage, // File name
+ GENERIC_READ, // Desired access
+ FILE_SHARE_READ, // Share mode
+ NULL, // Security attributes
+ OPEN_EXISTING, // Creation distribution
+ 0L, // Flags & Attributes
+ NULL ); // hTemplateFile
+ if( hFile == NULL )
+ {
+ m_hr = (HRESULT) GetLastError();
+ EXIT( L"Failed call to CreateFile()" );
+ }
+
+ // Get the time on the file.
+
+ if( !GetFileTime( hFile, // File to check
+ NULL, // Create Time
+ NULL, // Access Time
+ pft ) // Write Time
+ )
+ {
+ m_hr = (HRESULT) GetLastError();
+ EXIT( L"Failed call to GetFileTime()" );
+ }
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Close the file if we opened it.
+
+ if( hFile )
+ {
+ CloseHandle( hFile );
+ hFile = NULL;
+ }
+
+
+ DisplayErrors( bSuccess, L"CMoniker::GetTemporaryStorageTime()" );
+ return( bSuccess );
+
+} // CMoniker::GetTemporaryStorageTime()
+
+
+//+------------------------------------------------------------------------
+//
+// Function: CMoniker::TouchTemporaryStorage
+//
+// Synopsis: Set the Access time on the link source file.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: The link source file (identified by m_wszTemporaryStorage)
+// has its Access time set to the current time.
+//
+//+------------------------------------------------------------------------
+
+
+BOOL CMoniker::TouchTemporaryStorage( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+ HANDLE hFile = NULL;
+ STATSTG statStorage;
+ FILETIME ftNow;
+
+ // -----
+ // Begin
+ // -----
+
+ m_hr = NOERROR;
+
+ // Open the root Storage.
+
+ m_hr = StgOpenStorage( m_wszTemporaryStorage,
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
+ NULL,
+ 0L,
+ &m_pIStorage );
+ EXIT_ON_FAILED( L"Failed StgOpenStorage()" );
+
+ // Get the current time.
+
+ m_hr = CoFileTimeNow( &ftNow );
+ EXIT_ON_FAILED( L"Failed CoFileTimeNow()" );
+
+ // Set the access time
+
+ m_pIStorage->SetElementTimes( NULL, // Set the storage itself
+ NULL, // Create time
+ NULL, // Access time
+ &ftNow );
+ EXIT_ON_FAILED( L"Failed IStorage::SetTimes()" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we got the storage, release it.
+
+ if( m_pIStorage )
+ {
+ m_pIStorage->Release();
+ m_pIStorage = NULL;
+ }
+
+ DisplayErrors( bSuccess, L"CMoniker::TouchTemporaryStorage()" );
+ return( bSuccess );
+
+} // CMoniker::TouchTemporaryStorage()
+
+
+
+#ifdef _FUTURE_
+
+/*
+BOOL CMoniker::OpenLinkTrackingRegistryKey()
+{
+
+ BOOL bSuccess = FALSE;
+ DWORD dwDisposition = 0L;
+ long lResult = 0L;
+
+ m_hr = S_OK;
+
+ lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ OLETRACKING_KEY,
+ 0L,
+ KEY_ALL_ACCESS,
+ &m_hkeyLinkTracking
+ );
+
+ if( lResult != ERROR_SUCCESS
+ &&
+ lResult != ERROR_FILE_NOT_FOUND
+ )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegOpenKeyEx()" );
+ }
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::OpenLinkTrackingRegistryKey()" );
+ return( bSuccess );
+
+
+} // CMoniker::OpenLinkTrackingRegistryKey()
+
+
+BOOL CMoniker::CreateLinkTrackingRegistryKey()
+{
+
+ BOOL bSuccess = FALSE;
+ HKEY hkey = NULL;
+ DWORD dwDisposition = 0L;
+ long lResult = 0L;
+
+ m_hr = S_OK;
+
+ if( m_hkeyLinkTracking )
+ CloseLinkTrackingRegistryKey();
+
+ lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ OLETRACKING_KEY,
+ 0L,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &m_hkeyLinkTracking,
+ &dwDisposition
+ );
+
+ if( lResult != ERROR_SUCCESS )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegCreateKeyEx()" );
+ }
+
+ bSuccess = TRUE;
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::CreateLinkTrackingRegistryKey()" );
+ return( bSuccess );
+
+} // CMoniker::CreateLinkTrackingRegistryKey()
+
+
+
+BOOL CMoniker::CloseLinkTrackingRegistryKey()
+{
+ m_hr = S_OK;
+
+ if( m_hkeyLinkTracking )
+ RegCloseKey( m_hkeyLinkTracking );
+
+ m_hkeyLinkTracking = NULL;
+
+ return TRUE;
+
+} // CMoniker::CloseLinkTrackingRegistryKey()
+
+
+
+BOOL CMoniker::SaveRegistryTrackFlags()
+{
+ BOOL bSuccess = FALSE;
+
+ long lResult = 0L;
+ DWORD dwType = 0L;
+ DWORD dwcbData = sizeof( m_dwTrackFlags );
+
+
+ m_hr = S_OK;
+
+ if( !OpenLinkTrackingRegistryKey() )
+ EXIT( L"Could not open the registry" );
+
+ lResult = RegQueryValueEx( m_hkeyLinkTracking,
+ OLETRACKING_FILEMONIKER_VALUE,
+ NULL,
+ &dwType,
+ (LPBYTE) &m_dwTrackFlags,
+ &dwcbData );
+
+ if( lResult != ERROR_SUCCESS )
+ {
+ CloseLinkTrackingRegistryKey();
+
+ if( lResult != ERROR_FILE_NOT_FOUND )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegQueryValueEx()" );
+ }
+ }
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::SaveRegistryTrackFlags()" );
+ return( bSuccess );
+
+} // CMoniker::SaveRegistryTrackFlags()
+
+
+
+BOOL CMoniker::DeleteRegistryTrackFlags()
+{
+ BOOL bSuccess = FALSE;
+
+ long lResult = 0L;
+ DWORD dwType = 0L;
+ DWORD dwcbData = sizeof( m_dwTrackFlags );
+
+
+ m_hr = S_OK;
+
+ if( !CreateLinkTrackingRegistryKey() )
+ EXIT( L"Could not open the registry" );
+
+
+ lResult = RegDeleteValue( m_hkeyLinkTracking,
+ OLETRACKING_FILEMONIKER_VALUE );
+
+
+ if( lResult != ERROR_SUCCESS
+ &&
+ lResult != ERROR_FILE_NOT_FOUND
+ )
+ {
+ if( lResult != ERROR_FILE_NOT_FOUND )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegDeleteValue()" );
+ }
+ }
+
+ bSuccess = TRUE;
+
+Exit:
+
+ CloseLinkTrackingRegistryKey();
+
+ DisplayErrors( bSuccess, L"CMoniker::DeleteRegistryTrackFlags()" );
+ return( bSuccess );
+
+} // CMoniker::DeleteRegistryTrackFlags()
+
+
+
+BOOL CMoniker::RestoreRegistryTrackFlags()
+{
+ BOOL bSuccess = FALSE;
+ long lResult = 0L;
+
+
+ m_hr = S_OK;
+
+ // If the registry key doesn't exist, then there's no flags
+ // to restore.
+
+ if( m_hkeyLinkTracking )
+ {
+
+ lResult = RegSetValueEx( m_hkeyLinkTracking,
+ OLETRACKING_FILEMONIKER_VALUE,
+ 0L,
+ REG_DWORD,
+ (LPBYTE) &m_dwTrackFlags,
+ sizeof( m_dwTrackFlags )
+ );
+
+ if( lResult != ERROR_SUCCESS )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegSetValueEx()" );
+ }
+
+ CloseLinkTrackingRegistryKey();
+
+ }
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::RestoreRegistryTrackFlags()" );
+ return( bSuccess );
+
+} // CMoniker::RestoreRegistryTrackFlags()
+
+CMoniker::SetTrackFlagsInRegistry( DWORD dwTrackFlags )
+{
+ BOOL bSuccess = FALSE;
+ long lResult = 0L;
+ HKEY hkey = NULL;
+
+
+ m_hr = S_OK;
+
+ if( !CreateLinkTrackingRegistryKey() )
+ EXIT( L"Could not create registry key" );
+
+ lResult = RegSetValueEx( m_hkeyLinkTracking,
+ OLETRACKING_FILEMONIKER_VALUE,
+ 0L,
+ REG_DWORD,
+ (LPBYTE) &dwTrackFlags,
+ sizeof( dwTrackFlags )
+ );
+
+ if( lResult != ERROR_SUCCESS )
+ {
+ m_hr = (HRESULT) lResult;
+ EXIT( L"Failed RegSetValueEx()" );
+ }
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::SetTrackFlagsInRegistry()" );
+ return( bSuccess );
+
+} // CMoniker::SetTrackFlagsInRegistry()
+
+
+BOOL CMoniker::CreateFileMoniker()
+{
+
+ BOOL bSuccess = FALSE;
+
+ m_hr = S_OK;
+
+ // Free any existing IMoniker.
+
+ if( m_pIMoniker )
+ {
+ m_pIMoniker->Release();
+ m_pIMoniker = NULL;
+ }
+
+ // Create a root storage.
+
+ if( !CreateTemporaryStorage() )
+ EXIT( L"Could not create a temporary storage" );
+
+ // Create a default File Moniker on that root storage.
+
+ m_hr = ::CreateFileMoniker( m_wszTemporaryStorage, &m_pIMoniker );
+ EXIT_ON_FAILED( L"Failed CreateFileMoniker" );
+
+
+ bSuccess = TRUE;
+
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CMoniker::CreateFileMoniker" );
+ return( bSuccess );
+
+} // CMoniker::CreateFileMoniker()
+*/
+#endif // _FUTURE_