summaryrefslogtreecommitdiffstats
path: root/private/oleutest/cfmex/ctest.cxx
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/oleutest/cfmex/ctest.cxx
downloadNT4.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/ctest.cxx')
-rw-r--r--private/oleutest/cfmex/ctest.cxx1283
1 files changed, 1283 insertions, 0 deletions
diff --git a/private/oleutest/cfmex/ctest.cxx b/private/oleutest/cfmex/ctest.cxx
new file mode 100644
index 000000000..e2de08c3c
--- /dev/null
+++ b/private/oleutest/cfmex/ctest.cxx
@@ -0,0 +1,1283 @@
+
+
+//+=======================================================================
+//
+// File: CTest.cxx
+//
+// Purpose: Define the CTest class.
+//
+// This class is the test engine for the CreateFileMonikerEx
+// (CFMEx) DRTs. All interactions with monikers are handled
+// through the CMoniker class.
+//
+//+=======================================================================
+
+
+// -------------
+// Include Files
+// -------------
+
+#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 "CDir.hxx"
+#include "CMoniker.hxx"
+#include "CTest.hxx"
+
+
+//+------------------------------------------------------------------------
+//
+// Function: CTest::CTest
+//
+// Synopsis: Inititialize member variables.
+//
+// Inputs: None.
+//
+// Outputs: N/A
+//
+// Effects: All members are initialized/defaulted.
+//
+//+------------------------------------------------------------------------
+
+
+CTest::CTest( )
+{
+
+ m_lError = 0L;
+ *m_wszErrorMessage = L'\0';
+
+ m_pcDirectoryOriginal = NULL;
+ m_pcDirectoryFinal = NULL;
+
+} // CTest::CTest
+
+//+------------------------------------------------------------------------------
+//
+// Function: CTest::~CTest
+//
+// Synopsis: No action.
+//
+// Inputs: N/A
+//
+// Outputs: N/A
+//
+// Effects: None.
+//
+//+------------------------------------------------------------------------------
+
+
+CTest::~CTest()
+{
+} // CTest::~CTest
+
+
+//+-------------------------------------------------------------------------------
+//
+// Function: CTest::Initialize
+//
+// Synopsis: Inititialize a CTest object.
+//
+// Inputs: CDirectory objects representing the original and final
+// locations of a link source file. The original location
+// is used in CreateTemporaryStorage(), and the final location
+// is used in RenameTemporaryStorage().
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: m_cDirectoryOriginal and m_cDirectoryFinal are set.
+//
+//+-------------------------------------------------------------------------------
+
+
+BOOL CTest::Initialize( const CDirectory& cDirectoryOriginal,
+ const CDirectory& cDirectoryFinal
+ )
+{
+ // -----
+ // Begin
+ // -----
+
+ m_pcDirectoryOriginal = &cDirectoryOriginal;
+ m_pcDirectoryFinal = &cDirectoryFinal;
+
+ m_cMoniker.Initialize( cDirectoryOriginal, cDirectoryFinal );
+
+ // ----
+ // Exit
+ // ----
+
+ return TRUE;
+
+} // CTest::Initialize
+
+//+-------------------------------------------------------------------------
+//
+// Function: CTest::CreateFileMonikerEx
+//
+// Synopsis: Verify that CreateFileMonikerEx actually creates a
+// *tracking* file moniker. This is done by creating
+// the file moniker, renaming the link source,
+// Reducing the moniker, and getting the display name
+// of the reduced moniker. Note that this tests
+// both CreateFileMonikerEx and Reduce.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+-------------------------------------------------------------------------
+
+
+BOOL CTest::CreateFileMonikerEx( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ WCHAR wszDisplayName[ MAX_PATH + sizeof( L'\0' ) ];
+ IMoniker* pmnkReduced = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"CreateFileMonikerEx()\n" );
+ wprintf( L" Create a tracking file moniker (using CreateFileMonikerEx),\n"
+ L" move the represented file, Reduce the moniker, and get\n"
+ L" the display name from the reduced moniker. It should be the\n"
+ L" new file name. This test covers both CreateFileMonikerEx and\n"
+ L" Reduce.\n" );
+
+
+ // Create the tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Rename the link source file.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Reduce the tracking file moniker
+
+ if( !m_cMoniker.Reduce( INFINITE, &pmnkReduced ))
+ EXIT( L"Could not reduce the moniker" );
+
+ // Use the reduced (non-tracking) file moniker to get the display name.
+
+ if( !m_cMoniker.GetDisplayName( wszDisplayName, pmnkReduced ))
+ EXIT( L"Could not get the display name" );
+
+ // Validate the display name.
+
+ if( _wcsicmp( wszDisplayName, m_cMoniker.GetTemporaryStorageName() ))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::CreateFileMonikerEx()" );
+ return( bSuccess );
+
+} // CTest::CreateFileMonikerEx()
+
+
+//+--------------------------------------------------------------------------
+//
+// Function: CTest::GetDisplayName
+//
+// Synopsis: Create a tracking file moniker, get its display name,
+// rename the link source file, and get the display name again.
+// The value of the second display name will depend on whether
+// or not the original and final link source are within the set
+// of local indexed volumes.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+--------------------------------------------------------------------------
+
+
+BOOL CTest::GetDisplayName( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ WCHAR wszFinalDisplayName[ MAX_PATH + sizeof( L'\0' ) ];
+ WCHAR wszOriginalDisplayName[ MAX_PATH + sizeof( L'\0' ) ];
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"GetDisplayName()\n" );
+ wprintf( L" Create a tracking file moniker, move the represented file,\n"
+ L" and perform a GetDisplayName on the moniker. If the original\n"
+ L" and final locations of the source file are within the set of local\n"
+ L" indexed drives, the display name will represent the final file name.\n"
+ L" Otherwise, it will represent the original display name.\n" );
+
+ // Create a tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Get its display name.
+
+ if( !m_cMoniker.GetDisplayName( wszOriginalDisplayName ))
+ EXIT( L"Could not get the original display name" );
+
+ // Rename the link source.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Get the renamed moniker's display name.
+
+ if( !m_cMoniker.GetDisplayName( wszFinalDisplayName ))
+ EXIT( L"Could not get the final display name" );
+
+ // Was and is the link source on a local, indexed volume?
+
+ if( ( m_pcDirectoryOriginal->GetFileSystemType() == fstOFS )
+ &&
+ ( m_pcDirectoryOriginal->GetFileSystemType() == fstOFS )
+ )
+ {
+ // Yes, so the GetDisplayName should have tracked the rename.
+
+ if( _wcsicmp( wszFinalDisplayName, m_cMoniker.GetTemporaryStorageName() ))
+ EXIT( L"Failed" );
+ }
+ else
+ {
+ // No, so the GetDisplayName should have returned the original name.
+
+ if( _wcsicmp( wszOriginalDisplayName, wszFinalDisplayName ))
+ EXIT( L"Failed" );
+ }
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::GetDisplayName()" );
+ return( bSuccess );
+
+} // CTest::GetDisplayName()
+
+
+
+//+--------------------------------------------------------------------------
+//
+// Function: CTest::GetTimeOfLastChange
+//
+// Synopsis: Create a tracking file moniker, rename it, sleep, and
+// touch it. If the original and final link sources are
+// on local, indexed volumes, then a GetDisplayName should
+// return the final link source's time. Otherwise, it should
+// return the original link source's time.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+--------------------------------------------------------------------------
+
+
+BOOL CTest::GetTimeOfLastChange( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ FILETIME ftOriginal;
+ FILETIME ftFinal;
+ FILETIME ftMoniker;
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"GetTimeOfLastChange()\n" );
+ wprintf( L" Create a tracking file moniker and move it. Then touch (set the Access\n"
+ L" time) on the link source, and perform a GetTimeOfLastChange on the Moniker.\n"
+ L" If the original and final location of the link source is within the set\n"
+ L" of local indexed volumes, then the time returned from the moniker should\n"
+ L" match that of the post-touch link source. Otherwise it should match the\n"
+ L" link sources original time.\n" );
+
+ // Create a tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( TRACK_LOCALONLY ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Get the link source's current time.
+
+ if( !m_cMoniker.GetTemporaryStorageTime( &ftOriginal ))
+ EXIT( L"Could not get original file time" );
+
+ // Move the link source.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Delay so that when we touch the final link source, its time
+ // will be noticably different from the original link source's time.
+
+ {
+ wprintf( L" Sleeping to let the time change: " );
+ for( int i = 0; i < 10; i++ ) // Sleep for 5 seconds
+ {
+ wprintf( L"z" );
+ Sleep( 500 ); // 1/2 second
+ }
+ wprintf( L"\n" );
+ }
+
+ // Touch the final link source.
+
+ if( !m_cMoniker.TouchTemporaryStorage())
+ EXIT( L"Could not touch temporary storage" );
+
+ // Get the final link source's time from the file system.
+
+ if( !m_cMoniker.GetTemporaryStorageTime( &ftFinal ))
+ EXIT( L"could not get final file time" );
+
+ // Get the final link source's time from the moniker.
+
+ if( !m_cMoniker.GetTimeOfLastChange( &ftMoniker ))
+ EXIT( L"Could not get the time of last change" );
+
+ // Is the original & final location of the link source file
+ // in the set of local, indexed volumes?
+
+ if( ( m_pcDirectoryOriginal->GetFileSystemType() == fstOFS )
+ &&
+ ( m_pcDirectoryOriginal->GetFileSystemType() == fstOFS )
+ )
+ {
+ // Yes. GetTimeOfLastChange should therefore have found
+ // the time of the final link source file.
+
+ if( memcmp( &ftFinal, &ftMoniker, sizeof( FILETIME ) ))
+ EXIT( L"Failed" );
+ }
+ else
+ {
+ // No. GetTimeOfLastChange should therefore have returned
+ // the time of the original link source file.
+
+ if( memcmp( &ftOriginal, &ftMoniker, sizeof( FILETIME ) ))
+ EXIT( L"Failed" );
+ }
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::GetTimeOfLastChange()" );
+ return( bSuccess );
+
+} // CTest::GetTimeOfLastChange()
+
+
+//+--------------------------------------------------------------------
+//
+// Function: CTest::BindToObject
+//
+// Synopsis: Create a tracking file moniker, move the link source,
+// and attempt to bind to it with a BindToObject.
+// Since presumably the temporary file we're using as a link
+// source has no server, this will fail. But any failure
+// downstream of locating the link source file will be
+// ignored.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+--------------------------------------------------------------------
+
+
+BOOL CTest::BindToObject( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"BindToObject()\n" );
+ wprintf( L" Create a tracking file moniker, moved the represented file,\n"
+ L" and attempt a BindToStorage() (which should succeed).\n" );
+
+ // Create a tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Move the link source file.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Attempt a bind.
+
+ if( !m_cMoniker.BindToObject( ))
+ EXIT( L"Could not bind to Object" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::BindToObject()" );
+ return( bSuccess );
+
+} // CTest::BindToObject()
+
+
+//+-----------------------------------------------------------
+//
+// Function: CTest::IPersist
+//
+// Synopsis: Create a tracking file moniker, move the link
+// source, and perform the CMoniker::SaveDeleteLoad
+// test.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise
+//
+// Effects: None.
+//
+//+-----------------------------------------------------------
+
+
+BOOL CTest::IPersist( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"IPersist()\n" );
+ wprintf( L" Create a tracking file moniker (using CreateFileMonikerEx), and\n"
+ L" save it to a Stream. Delete the moniker, create a new one using\n"
+ L" CreateFileMoniker, load it from the Stream, and verify that the resulting\n"
+ L" file moniker is tracking.\n" );
+
+ // Create a tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Rename the link source.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Save the moniker, deleted, create a new moniker, and reload it.
+
+ if( !m_cMoniker.SaveDeleteLoad( ))
+ EXIT( L"Failed SaveDeleteLoad" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::IPersist()" );
+ return( bSuccess );
+
+} // CTest::IPersist()
+
+
+//+----------------------------------------------------------------------
+//
+// Function: CTest::ComposeWith
+//
+// Synopsis: Create a tracking file moniker, and use it in the
+// CMoniker::ComposeWith operation.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+----------------------------------------------------------------------
+
+BOOL CTest::ComposeWith( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ IMoniker* pmnkReduced = NULL;
+ WCHAR wszDisplayName[ MAX_PATH + sizeof( L'\0' )];
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0;
+
+ wprintf( L"ComposeWith()\n" );
+ wprintf( L" Create a tracking file moniker, and compose it with a non-tracking\n"
+ L" file moniker on the right. The resulting moniker should be tracking.\n" );
+
+ // Create the tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Perform the ComposeWith operation.
+
+ if( !m_cMoniker.ComposeWith( ))
+ EXIT( L"Failed ComposeWith" );
+
+ // Move the link source file.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Reduce the composed moniker.
+
+ if( !m_cMoniker.Reduce( INFINITE, &pmnkReduced ))
+ EXIT( L"Could not reduce the moniker" );
+
+ // Get the display name on the reduced moniker.
+
+ if( !m_cMoniker.GetDisplayName( wszDisplayName, pmnkReduced ))
+ EXIT( L"Could not get the display name" );
+
+ // Verify that the name from the moniker is the actual link source
+ // file's new name.
+
+ if( _wcsicmp( wszDisplayName, m_cMoniker.GetTemporaryStorageName() ))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::ComposeWith()" );
+ return( bSuccess );
+
+} // CTest::ComposeWith()
+
+
+//+------------------------------------------------------------------
+//
+// Function: CTest::BindToStorage
+//
+// Synopsis: Create a tracking file moniker, and perform the
+// CMoniker::BindToStorage operation.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+//+------------------------------------------------------------------
+
+
+BOOL CTest::BindToStorage( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0;
+
+ wprintf( L"BindToStorage()\n" );
+ wprintf( L" Create a tracking file moniker (using CreateFileMonikerEx),\n"
+ L" move the represented file, Reduce the moniker, and get\n"
+ L" the display name from the reduced moniker. It should be the\n"
+ L" new file name. This test covers both CreateFileMonikerEx and\n"
+ L" Reduce.\n" );
+
+ // Create the tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Move the link source file.
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ // Bind to the Storage
+
+ if( !m_cMoniker.BindToStorage( ))
+ EXIT( L"Could not bind to Storage" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ DisplayErrors( bSuccess, L"CTest::BindToStorage()" );
+ return( bSuccess );
+
+} // CTest::BindToStorage()
+
+
+//+--------------------------------------------------------------------------
+//
+// Function: CTest::DeleteLinkSource
+//
+// Synopsis: Create a tracking file moniker, delete the link source,
+// and attempt a Reduce. The Reduce should not fail, but
+// it should return an HResult of MK_S_REDUCED_TO_SELF.
+//
+// Inputs: Tick count limit on the length of the Reduce operation.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+--------------------------------------------------------------------------
+
+BOOL CTest::DeleteLinkSource( DWORD dwDelay )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ WCHAR wszTimeout[ 80 ];
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0L;
+
+ // Generate a string which shows what the delay is.
+
+ switch( dwDelay )
+ {
+ case 0:
+ wcscpy( wszTimeout, L"instant timeout" );
+ break;
+
+ case INFINITE:
+ wcscpy( wszTimeout, L"infinite timeout" );
+ break;
+
+ default:
+ wsprintf( wszTimeout, L"%d ms timeout", dwDelay );
+ }
+
+ // Display a header.
+
+ wprintf( L"Delete Link Source (%s)\n",
+ wszTimeout );
+ wprintf( L" Create a tracking file moniker, then delete the link source, and\n"
+ L" attempt a reduce with a %s.\n",
+ wszTimeout );
+
+ // Create a tracking file moniker.
+
+ if( !m_cMoniker.CreateFileMonikerEx( ) )
+ EXIT( L"Could not CreateFileMonikerEx" );
+
+ // Delete the link source file.
+
+ if( !m_cMoniker.DeleteTemporaryStorage() )
+ EXIT( L"Could not delete temporary storage" );
+
+ // Tell CMoniker not to alarm the user with error messages.
+
+ m_cMoniker.SuppressErrorMessages( TRUE );
+
+ // Reduce the moniker, and verify it returns the proper Success code.
+
+ if( !m_cMoniker.Reduce( dwDelay )
+ ||
+ m_cMoniker.GetHResult() != MK_S_REDUCED_TO_SELF
+ )
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+ m_cMoniker.SuppressErrorMessages( FALSE );
+
+ DisplayErrors( bSuccess, L"CTest::DeleteLinkSource()" );
+ return( bSuccess );
+
+} // CTest::DeleteLinkSource()
+
+
+//+------------------------------------------------------------------
+//
+// Function: CTest::GetOversizedBindOpts
+//
+// Synopsis: Test a bind context's ability to return a BIND_OPTS
+// which is larger than expected.
+//
+// First, initialize the default BIND_OPTS in the bind
+// context to 1s. Then, ask for a large BIND_OPTS.
+// The resulting buffer should have 1s up to the size of
+// the normal BIND_OPTS, and 0s for the remainder of the
+// buffer. The length, however, should be that of the large
+// buffer.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+------------------------------------------------------------------
+
+
+BOOL CTest::GetOversizedBindOpts( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ BIND_OPTS bind_opts;
+ LPBIND_OPTS pbind_optsLarge = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+ LPBIND_OPTS pbind_optsExpected = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0L;
+
+ wprintf( L"Get Oversized BindOpts\n" );
+ wprintf( L" Create a buffer which is much larger than a normal BIND_OPTS, and\n"
+ L" use it to request the BIND_OPTS from a bind context. The length\n"
+ L" of the resulting buffer should be the large value, and the extra\n"
+ L" room in the buffer should be all 0s.\n" );
+
+
+ // Validate our 'new' operations.
+
+ if( pbind_optsLarge == NULL )
+ EXIT( L"Could not allocate pbind_optsLarge" );
+ pbind_optsLarge->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ if( pbind_optsExpected == NULL )
+ EXIT( L"Could not allocate pbind_optsExpected" );
+ pbind_optsExpected->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+
+ // Initialize the bind_opts (normal sized) in the bind context to 1s.
+
+ if( !m_cMoniker.InitializeBindContext() )
+ EXIT( L"Could not initialize the bind context" );
+
+ memset( &bind_opts, 1, sizeof( bind_opts ));
+ bind_opts.cbStruct = sizeof( bind_opts );;
+
+ m_lError = m_cMoniker.GetBindCtx()->SetBindOptions( &bind_opts );
+ if( FAILED( m_lError )) EXIT( L"Could not set original bind options" );
+
+ // Initialize the large bind_opts to 2s, then retrieve the bind_opts into
+ // this structure. This is done to verify that the GetBindOptions below
+ // fills in the entire requested buffer (overwirting all of the 2s).
+
+ memset( pbind_optsLarge, 2, SIZE_OF_LARGE_BIND_OPTS );
+ pbind_optsLarge->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ m_lError = m_cMoniker.GetBindCtx()->GetBindOptions( pbind_optsLarge );
+ if( FAILED( m_lError )) EXIT( L"Could not get large bind options" );
+
+ // The returned structure should have the large cbStruct, 1s up to
+ // the length of BIND_OPTS, and 0s after that.
+
+ memset( pbind_optsExpected, 0, SIZE_OF_LARGE_BIND_OPTS );
+ memset( pbind_optsExpected, 1, sizeof( bind_opts ));
+ pbind_optsExpected->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ if( memcmp( pbind_optsLarge, pbind_optsExpected, SIZE_OF_LARGE_BIND_OPTS ))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CTest::GetOversizedBindOpts()" );
+ return( bSuccess );
+
+} // CTest::GetOversizeBindOpts()
+
+
+
+//+----------------------------------------------------------------
+//
+// Function: CTest::GetUndersizedBindOpts
+//
+// Synopsis: Create a bind context, and initialize the data in its
+// BIND_OPTS to 1s. Create a normal BIND_OPTS-sized buffer,
+// initialize it to 2s, then use it to get a small-sized
+// BIND_OPTS from the bind context. The resulting buffer
+// should have a small length, a small number of 1s,
+// and 2s for the remainder of the buffer.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+----------------------------------------------------------------
+
+
+
+BOOL CTest::GetUndersizedBindOpts( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ LPBIND_OPTS pbind_optsSmall = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+ LPBIND_OPTS pbind_optsExpected = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+ BIND_OPTS bind_opts;
+ bind_opts.cbStruct = sizeof( bind_opts );
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0L;
+
+ wprintf( L"Get Undersized BindOpts\n" );
+ wprintf( L" Get the BIND_OPTS from a bind context, but only providing a small\n"
+ L" buffer, and verify that only that portion of the actual BIND_OPTS\n"
+ L" is returned.\n" );
+
+ // Validate our 'new's.
+
+ if( pbind_optsSmall == NULL )
+ EXIT( L"Could not allocate pbind_optsSmall" );
+ pbind_optsSmall->cbStruct = SIZE_OF_SMALL_BIND_OPTS;
+
+ if( pbind_optsExpected == NULL )
+ EXIT( L"Could not allocate pbind_optsExpected" );
+ pbind_optsExpected->cbStruct = SIZE_OF_SMALL_BIND_OPTS;
+
+
+ // Initialize the bind_opts (normal sized) in the bind context to 1s.
+
+ if( !m_cMoniker.InitializeBindContext() )
+ EXIT( L"Could not initialize the bind context" );
+
+ memset( &bind_opts, 1, sizeof( bind_opts ));
+ bind_opts.cbStruct = sizeof( bind_opts );;
+
+ m_lError = m_cMoniker.GetBindCtx()->SetBindOptions( &bind_opts );
+ if( FAILED( m_lError )) EXIT( L"Could not set original bind options" );
+
+
+ // Initialize the small bind_opts to 2s, then retrieve the bind_opts into
+ // this structure.
+
+ memset( pbind_optsSmall, 2, SIZE_OF_LARGE_BIND_OPTS );
+ pbind_optsSmall->cbStruct = SIZE_OF_SMALL_BIND_OPTS;
+
+ m_lError = m_cMoniker.GetBindCtx()->GetBindOptions( pbind_optsSmall );
+ if( FAILED( m_lError )) EXIT( L"Could not get small bind options" );
+
+ // The returned structure should have the small cbStruct, 1s up to
+ // the end of the small buffer, and 2s to the end of the real buffer.
+
+ memset( pbind_optsExpected, 2, SIZE_OF_LARGE_BIND_OPTS );
+ memset( pbind_optsExpected, 1, SIZE_OF_SMALL_BIND_OPTS );
+ pbind_optsExpected->cbStruct = SIZE_OF_SMALL_BIND_OPTS;
+
+ if( memcmp( pbind_optsSmall, pbind_optsExpected, SIZE_OF_LARGE_BIND_OPTS ))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CTest::GetUndersizedBindOpts()" );
+ return( bSuccess );
+
+} // CTest::GetUndersizedBindOpts()
+
+
+//+----------------------------------------------------------------
+//
+// Function: CTest::SetOversizedBindOpts
+//
+// Synopsis: Create a large BIND_OPTS buffer, set it in
+// a bind context, and verify that it can be read back.
+//
+// Inputs: None.
+//
+// Outputs: TRUE if successful, FALSE otherwise.
+//
+// Effects: None.
+//
+//+----------------------------------------------------------------
+
+BOOL CTest::SetOversizedBindOpts( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ LPBIND_OPTS pbind_optsLarge = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+ LPBIND_OPTS pbind_optsExpected = (LPBIND_OPTS) new BYTE[ SIZE_OF_LARGE_BIND_OPTS ];
+
+ // -----
+ // Begin
+ // -----
+
+ wprintf( L"Set Oversized BindOpts\n" );
+ wprintf( L" Set a larger-than-usual BIND_OPTS in a bind context, and verify\n"
+ L" that it can be read back in its entirety.\n" );
+
+ // Validate our 'new's.
+
+ if( pbind_optsLarge == NULL )
+ EXIT( L"Could not allocate pbind_optsLarge" );
+ pbind_optsLarge->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ if( pbind_optsExpected == NULL )
+ EXIT( L"Could not allocate pbind_optsExpected" );
+ pbind_optsExpected->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ // Initialize the large bind_opts to 1s, then set the large BIND_OPTS
+ // into the bind context.
+
+ if( !m_cMoniker.InitializeBindContext() )
+ EXIT( L"Could not initialize the bind context" );
+
+ memset( pbind_optsLarge, 1, SIZE_OF_LARGE_BIND_OPTS );
+ pbind_optsLarge->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ m_lError = m_cMoniker.GetBindCtx()->SetBindOptions( pbind_optsLarge );
+ if( FAILED( m_lError )) EXIT( L"Could not set large bind options" );
+
+ // Get the BIND_OPTS back from the bind context, and verify that it's
+ // what we set.
+
+ memset( pbind_optsLarge, 0, SIZE_OF_LARGE_BIND_OPTS );
+ pbind_optsLarge->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+ m_lError = m_cMoniker.GetBindCtx()->GetBindOptions( pbind_optsLarge );
+
+ memset( pbind_optsExpected, 1, SIZE_OF_LARGE_BIND_OPTS );
+ pbind_optsExpected->cbStruct = SIZE_OF_LARGE_BIND_OPTS;
+
+ if( memcmp( pbind_optsLarge, pbind_optsExpected, SIZE_OF_LARGE_BIND_OPTS ))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CTest::SetOversizedBindOpts()" );
+ return( bSuccess );
+
+} // CTest::SetOversizeBindOpts()
+
+
+//+------------------------------------------------------------
+//
+// Function: CTest::SetUndersizedBindOpts
+//
+// Synopsis: Create a bind context, and initialize its BIND_OPTS to
+// all 1s. Then, set a small BIND_OPTS in the bind context
+// which is set to 2s. Read back the whold BIND_OPTS, and
+// verify that it has the normal length, 2s at the
+// beginning, and 1s to the end.
+//
+// Inputs: None.
+//
+// Output: TRUE if successful, FALSE otherwise.
+//
+//+------------------------------------------------------------
+
+
+BOOL CTest::SetUndersizedBindOpts( )
+{
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ BOOL bSuccess = FALSE;
+
+ BIND_OPTS bind_opts;
+ BIND_OPTS bind_optsExpected;
+
+ // -----
+ // Begin
+ // -----
+
+ m_lError = 0L;
+
+ wprintf( L"Set Undersized BindOpts\n" );
+ wprintf( L" Initialize a BIND_OPTS in a bind context to 1s, then set a smaller\n"
+ L" BIND_OPTS in it set to 2s. When the buffer is read back, it should\n"
+ L" have 2s up to the small buffer size, followed by 1s.\n" );
+
+ // Initialize the bind context's BIND_OPTS (normal sized) to 1s.
+
+ if( !m_cMoniker.InitializeBindContext() )
+ EXIT( L"Could not initialize the bind context" );
+
+ memset( &bind_opts, 1, sizeof( bind_opts ));
+ bind_opts.cbStruct = sizeof( bind_opts );
+ m_lError = m_cMoniker.GetBindCtx()->SetBindOptions( &bind_opts );
+ if( FAILED( m_lError )) EXIT( L"Could not set initial BIND_OPTS" );
+
+ // Now set a smaller BIND_OPTS. But initialize the local BIND_OPTS to all
+ // 2s, so that we can verify that only part of the buffer is put into the
+ // bind context.
+
+ memset( &bind_opts, 2, sizeof( bind_opts ) );
+ bind_opts.cbStruct = SIZE_OF_SMALL_BIND_OPTS;
+ m_lError = m_cMoniker.GetBindCtx()->SetBindOptions( &bind_opts );
+ if( FAILED( m_lError )) EXIT( L"Could not set small BIND_OPTS" );
+
+ // The resulting BIND_OPTS in the bind context should have 2s up
+ // to SIZE_OF_SMALL_BIND_OPTS, and 1s for the remainder of the buffer.
+
+ bind_opts.cbStruct = sizeof( bind_opts );
+ m_lError = m_cMoniker.GetBindCtx()->GetBindOptions( &bind_opts );
+ if( FAILED( m_lError )) EXIT( L"Could not get BIND_OPTS" );
+
+ memset( &bind_optsExpected, 1, sizeof( bind_opts ));
+ memset( &bind_optsExpected, 2, SIZE_OF_SMALL_BIND_OPTS );
+ bind_optsExpected.cbStruct = sizeof( bind_opts );
+
+ if( memcmp( &bind_opts, &bind_optsExpected, sizeof( bind_opts )))
+ EXIT( L"Failed" );
+
+
+ bSuccess = TRUE;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DisplayErrors( bSuccess, L"CTest::SetUndersizedBindOpts()" );
+ return( bSuccess );
+
+} // CTest::SetUndersizedBindOpts()
+
+
+#ifdef _FUTURE_
+
+BOOL CTest::CFMWithRegistryClear( )
+{
+ BOOL bSuccess = FALSE;
+ WCHAR wszDisplayName[ MAX_PATH + sizeof( L'\0' ) ];
+
+ if( !m_cMoniker.SaveRegistryTrackFlags() )
+ EXIT( L"Could not save the existing track flags in the registry" );
+
+ if( !m_cMoniker.DeleteRegistryTrackFlags() )
+ EXIT( L"Could not delete the existing track flags in the registry" );
+
+ if( !m_cMoniker.CreateFileMoniker() )
+ EXIT( L"Could not CreateFileMoniker" );
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ if( !m_cMoniker.GetDisplayName( wszDisplayName ))
+ EXIT( L"Could not get the display name" );
+
+ if( !_wcsicmp( wszDisplayName, m_cMoniker.GetTemporaryStorageName() ))
+ EXIT( L"Test failed: A moniker was created using CreateFileMoniker, after\n"
+ L" the Track Flags had been cleared from the Registry.\n"
+ L" The underlying root storage was then renamed.\n"
+ L" But a GetDisplayName then showed the new name, implying\n"
+ L" that the created moniker is using tracking (which it\n"
+ L" should not, because without the Track Flags set there\n"
+ L" should be no tracking).\n" );
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ if( !m_cMoniker.RestoreRegistryTrackFlags() )
+ ERROR_IN_EXIT( L"Could not restore Track Flags in Registry" );
+
+
+ DisplayErrors( bSuccess, L"CTest::CFMWithRegistryClear" );
+ return( bSuccess );
+
+} // CTest::CFMWithRegistryClear
+
+
+
+
+BOOL CTest::CFMWithRegistrySet( )
+{
+ BOOL bSuccess = FALSE;
+ WCHAR wszDisplayName[ MAX_PATH + sizeof( L'\0' ) ];
+
+ if( !m_cMoniker.SaveRegistryTrackFlags() )
+ EXIT( L"Could not save the existing track flags in the registry" );
+
+ if( !m_cMoniker.SetTrackFlagsInRegistry( TRACK_LOCALONLY ) )
+ EXIT( L"Could not set track flags in the registry" );
+
+ if( !m_cMoniker.CreateFileMoniker() )
+ EXIT( L"Could not CreateFileMoniker" );
+
+ if( !m_cMoniker.RenameTemporaryStorage() )
+ EXIT( L"Could not rename the temporary storage file" );
+
+ if( !m_cMoniker.GetDisplayName( wszDisplayName ))
+ EXIT( L"Could not get the display name" );
+
+ if( _wcsicmp( wszDisplayName, m_cMoniker.GetTemporaryStorageName() ))
+ EXIT( L"Test failed: A moniker was created using CreateFileMoniker, after\n"
+ L" setting the TRACK_LOCALONLY flag in the Registry.\n"
+ L" However, after moving the linked file, GetDisplayName\n"
+ L" did not return the new name.\n" );
+
+
+ bSuccess = TRUE;
+
+Exit:
+
+ m_cMoniker.DeleteTemporaryStorage();
+
+ if( !m_cMoniker.RestoreRegistryTrackFlags() )
+ ERROR_IN_EXIT( L"Could not restore Track Flags in Registry" );
+
+
+ DisplayErrors( bSuccess, L"CTest::CFMWithRegistrySet()" );
+ return( bSuccess );
+
+} // CTest::CFMWithRegistrySet
+
+
+#endif // _FUTURE_