//+======================================================================= // // 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 #include #include #include #include #include #include #include #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_