diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/oleutest/cfmex/cmoniker.cxx | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/oleutest/cfmex/cmoniker.cxx')
-rw-r--r-- | private/oleutest/cfmex/cmoniker.cxx | 1684 |
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_ |