1182 lines
35 KiB
C++
1182 lines
35 KiB
C++
//+------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996-2000.
|
|
//
|
|
// File: propret.cxx
|
|
//
|
|
// Contents: Generic property retriever filesystems
|
|
//
|
|
// Classes: CGenericPropRetriever
|
|
//
|
|
// History: 12-Dec-96 SitaramR Created
|
|
//
|
|
//-------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <propret.hxx>
|
|
#include <seccache.hxx>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::CGenericPropRetriever
|
|
//
|
|
// Synopsis: Extracts property and object tables from the catalog.
|
|
//
|
|
// Arguments: [cat] -- Catalog
|
|
// [pQueryPropMapper] -- Pid Remapper associated with the query
|
|
// [secCache] -- Cache of AccessCheck() results
|
|
// [pScope] -- Scope (for fixup match) if client is going
|
|
// through rdr/svr, else 0.
|
|
// [amAlreadyAccessChecked] -- Don't need to re-check for this
|
|
// access mask.
|
|
//
|
|
// History: 21-Aug-91 KyleP Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGenericPropRetriever::CGenericPropRetriever( PCatalog & cat,
|
|
ICiQueryPropertyMapper *pQueryPropMapper,
|
|
CSecurityCache & secCache,
|
|
CRestriction const * pScope,
|
|
ACCESS_MASK amAlreadyAccessChecked )
|
|
: _cat( cat ),
|
|
_pQueryPropMapper( pQueryPropMapper ),
|
|
_secCache( secCache ),
|
|
_widPrimedForPropRetrieval( widInvalid ),
|
|
_remoteAccess( cat.GetImpersonationTokenCache() ),
|
|
_pScope( pScope ),
|
|
_ulAttribFilter( cat.GetRegParams()->FilterDirectories() ?
|
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :
|
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_DIRECTORY ),
|
|
_pPropRec( 0 ),
|
|
_cRefs( 1 ),
|
|
_amAlreadyAccessChecked( amAlreadyAccessChecked )
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::~CGenericPropRetriever, public
|
|
//
|
|
// Synopsis: Closes catalog tables associated with this instance.
|
|
//
|
|
// History: 21-Aug-91 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGenericPropRetriever::~CGenericPropRetriever()
|
|
{
|
|
Quiesce();
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::Quiesce, public
|
|
//
|
|
// Synopsis: Close any open resources.
|
|
//
|
|
// History: 3-May-1994 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CGenericPropRetriever::Quiesce()
|
|
{
|
|
_propMgr.Close();
|
|
_cat.CloseValueRecord( _pPropRec );
|
|
_pPropRec = 0;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::RetrieveValueByPid
|
|
//
|
|
// Effects: Fetch value from the property cache.
|
|
//
|
|
// Arguments: [pid] -- Property to fetch
|
|
// [pbData] -- Place to return the value
|
|
// [pcb] -- On input, the maximum number of bytes to
|
|
// write at pbData. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 12-Dec-96 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
inline BYTE * PastHeader( PROPVARIANT * ppv )
|
|
{
|
|
return( (BYTE *)ppv + sizeof( PROPVARIANT ) );
|
|
}
|
|
|
|
|
|
SCODE STDMETHODCALLTYPE CGenericPropRetriever::RetrieveValueByPid( PROPID pid,
|
|
PROPVARIANT *pbData,
|
|
ULONG *pcb )
|
|
{
|
|
static const UNICODE_STRING EmptyUnicodeString = { 0, 0, 0 };
|
|
|
|
if ( widInvalid == _widPrimedForPropRetrieval )
|
|
return CI_E_WORKID_NOTVALID;
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
unsigned cb = sizeof( PROPVARIANT );
|
|
|
|
//
|
|
// System properties are retrieved directly from FindFirst buffer.
|
|
// User properties must be retrieved through the standard retrieval
|
|
// mechanism.
|
|
//
|
|
|
|
switch ( pid )
|
|
{
|
|
case pidDirectory:
|
|
{
|
|
pbData->vt = VT_LPWSTR;
|
|
pbData->pwszVal = (WCHAR *)PastHeader(pbData);
|
|
|
|
unsigned cbExtra = 0;
|
|
|
|
// If the client is remote, apply the fixup to the path
|
|
|
|
if ( IsClientRemote() )
|
|
{
|
|
XGrowable<WCHAR> xwcBuf;
|
|
|
|
cbExtra = BuildPath( GetPath(),
|
|
& EmptyUnicodeString,
|
|
xwcBuf );
|
|
if ( 0 != cbExtra )
|
|
{
|
|
unsigned cwcBuf = ( *pcb - sizeof PROPVARIANT ) / sizeof WCHAR;
|
|
unsigned cwc = FixupPath( xwcBuf.Get(),
|
|
pbData->pwszVal,
|
|
cwcBuf );
|
|
cbExtra = (1 + cwc) * sizeof WCHAR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cbExtra = BuildPath( GetPath(),
|
|
& EmptyUnicodeString,
|
|
pbData->pwszVal,
|
|
*pcb - sizeof PROPVARIANT );
|
|
}
|
|
|
|
if ( 0 == cbExtra )
|
|
pbData->vt = VT_EMPTY;
|
|
else
|
|
cb += cbExtra;
|
|
|
|
break;
|
|
}
|
|
|
|
case pidClassId:
|
|
{
|
|
//
|
|
// If it's a Docfile, retrieve the class ID from the Docfile,
|
|
// otherwise, just return a default file or directory class id.
|
|
//
|
|
|
|
pbData->vt = VT_CLSID;
|
|
cb += sizeof( GUID );
|
|
|
|
if ( cb <= *pcb )
|
|
{
|
|
pbData->puuid = (GUID *)PastHeader(pbData);
|
|
SCODE sc = E_FAIL;
|
|
|
|
|
|
CFunnyPath funnyBuf;
|
|
if ( 0 == BuildPath( GetPath(), GetName(), funnyBuf ) )
|
|
{
|
|
pbData->vt = VT_EMPTY;
|
|
cb -= sizeof(GUID);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Try to retrieve the class id
|
|
//
|
|
|
|
sc = GetClassFile ( funnyBuf.GetPath(), pbData->puuid );
|
|
|
|
if ( FAILED(sc) )
|
|
{
|
|
// OLE was unable to obtain or infer the class id
|
|
|
|
cb -= sizeof( GUID );
|
|
pbData->vt = VT_EMPTY;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case pidPath:
|
|
{
|
|
pbData->vt = VT_LPWSTR;
|
|
pbData->pwszVal = (WCHAR *)PastHeader(pbData);
|
|
|
|
unsigned cbExtra = 0;
|
|
|
|
// If the client is remote, apply the fixup to the path
|
|
|
|
if ( IsClientRemote() )
|
|
{
|
|
XGrowable<WCHAR> xwcBuf;
|
|
|
|
cbExtra = BuildPath( GetPath(),
|
|
GetName(),
|
|
xwcBuf );
|
|
if ( 0 != cbExtra )
|
|
{
|
|
unsigned cwcBuf = ( *pcb - sizeof PROPVARIANT ) / sizeof WCHAR;
|
|
unsigned cwc = FixupPath( xwcBuf.Get(),
|
|
pbData->pwszVal,
|
|
cwcBuf );
|
|
cbExtra = (1 + cwc) * sizeof WCHAR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cbExtra = BuildPath( GetPath(),
|
|
GetName(),
|
|
pbData->pwszVal,
|
|
*pcb - sizeof PROPVARIANT );
|
|
}
|
|
|
|
if ( 0 == cbExtra )
|
|
pbData->vt = VT_EMPTY;
|
|
else
|
|
cb += cbExtra;
|
|
|
|
break;
|
|
}
|
|
|
|
case pidVirtualPath:
|
|
{
|
|
UNICODE_STRING const * pPath = GetVirtualPath();
|
|
|
|
if ( 0 == pPath )
|
|
pbData->vt = VT_EMPTY;
|
|
else
|
|
{
|
|
pbData->vt = VT_LPWSTR;
|
|
pbData->pwszVal = (WCHAR *)PastHeader(pbData);
|
|
|
|
cb += BuildPath( pPath, GetName(), pbData->pwszVal, *pcb - sizeof(PROPVARIANT) );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case pidName:
|
|
cb = *pcb;
|
|
StringToVariant( GetName(), pbData, &cb );
|
|
break;
|
|
|
|
case pidShortName:
|
|
cb = *pcb;
|
|
StringToVariant( GetShortName(), pbData, &cb );
|
|
break;
|
|
|
|
case pidLastChangeUsn:
|
|
pbData->vt = VT_I8;
|
|
pbData->hVal.QuadPart = 1; // First legal USN
|
|
break;
|
|
|
|
case pidSize:
|
|
pbData->vt = VT_I8;
|
|
pbData->hVal.QuadPart = ObjectSize();
|
|
|
|
if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
#if CIDBG == 1
|
|
if ( VT_I8 == pbData->vt )
|
|
Win4Assert( 0xdddddddddddddddd != pbData->hVal.QuadPart );
|
|
#endif // CIDBG == 1
|
|
|
|
break;
|
|
|
|
case pidAttrib:
|
|
pbData->vt = VT_UI4;
|
|
pbData->ulVal = Attributes();
|
|
|
|
if ( pbData->ulVal == 0xFFFFFFFF )
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
#if CIDBG == 1
|
|
if ( VT_UI4 == pbData->vt )
|
|
Win4Assert( 0xdddddddd != pbData->ulVal );
|
|
#endif // CIDBG == 1
|
|
|
|
break;
|
|
|
|
case pidWriteTime:
|
|
pbData->vt = VT_FILETIME;
|
|
pbData->hVal.QuadPart = ModifyTime();
|
|
|
|
if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
|
|
case pidCreateTime:
|
|
pbData->vt = VT_FILETIME;
|
|
pbData->hVal.QuadPart = CreateTime();
|
|
|
|
if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
|
|
case pidAccessTime:
|
|
pbData->vt = VT_FILETIME;
|
|
pbData->hVal.QuadPart = AccessTime();
|
|
|
|
if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
|
|
case pidStorageType:
|
|
pbData->vt = VT_UI4;
|
|
pbData->ulVal = StorageType();
|
|
|
|
if ( 0xFFFFFFFF == pbData->ulVal )
|
|
{
|
|
//
|
|
// Try VRootType
|
|
//
|
|
|
|
if ( GetVRootType( pbData->ulVal ) )
|
|
{
|
|
if ( pbData->ulVal & PCatalog::NNTPRoot )
|
|
pbData->ulVal = 1;
|
|
else
|
|
pbData->ulVal = 0;
|
|
}
|
|
else
|
|
pbData->vt = VT_EMPTY;
|
|
}
|
|
break;
|
|
|
|
case pidPropertyStoreLevel:
|
|
pbData->vt = VT_UI4;
|
|
pbData->ulVal = StorageLevel();
|
|
break;
|
|
|
|
case pidPropDataModifiable:
|
|
pbData->vt = VT_BOOL;
|
|
pbData->boolVal = IsModifiable() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
break;
|
|
|
|
case pidVRootUsed:
|
|
{
|
|
if ( GetVRootType( pbData->ulVal ) )
|
|
{
|
|
pbData->vt = VT_BOOL;
|
|
|
|
if ( pbData->ulVal & PCatalog::UsedRoot )
|
|
pbData->boolVal = VARIANT_TRUE;
|
|
else
|
|
pbData->boolVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
}
|
|
|
|
case pidVRootAutomatic:
|
|
{
|
|
if ( GetVRootType( pbData->ulVal ) )
|
|
{
|
|
pbData->vt = VT_BOOL;
|
|
|
|
if ( pbData->ulVal & PCatalog::AutomaticRoot )
|
|
pbData->boolVal = VARIANT_TRUE;
|
|
else
|
|
pbData->boolVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
}
|
|
|
|
case pidVRootManual:
|
|
{
|
|
if ( GetVRootType( pbData->ulVal ) )
|
|
{
|
|
pbData->vt = VT_BOOL;
|
|
|
|
if ( pbData->ulVal & PCatalog::ManualRoot )
|
|
pbData->boolVal = VARIANT_TRUE;
|
|
else
|
|
pbData->boolVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
pbData->vt = VT_EMPTY;
|
|
|
|
break;
|
|
}
|
|
|
|
case pidPropertyGuid:
|
|
cb += sizeof( GUID );
|
|
|
|
if ( cb <= *pcb )
|
|
{
|
|
pbData->puuid = (GUID *)PastHeader(pbData);
|
|
|
|
if ( GetPropGuid( *pbData->puuid ) )
|
|
pbData->vt = VT_CLSID;
|
|
else
|
|
{
|
|
cb -= sizeof(GUID);
|
|
pbData->vt = VT_EMPTY;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case pidPropertyDispId:
|
|
pbData->ulVal = GetPropPropid();
|
|
|
|
if ( pbData->ulVal == pidInvalid )
|
|
pbData->vt = VT_EMPTY;
|
|
else
|
|
pbData->vt = VT_UI4;
|
|
break;
|
|
|
|
case pidPropertyName:
|
|
cb = *pcb;
|
|
StringToVariant( GetPropName(), pbData, &cb );
|
|
break;
|
|
|
|
default:
|
|
{
|
|
//
|
|
// First, try the property cache.
|
|
//
|
|
|
|
cb = *pcb;
|
|
|
|
BOOL fTryOLE = TRUE;
|
|
|
|
if ( FetchValue( pid, pbData, &cb ) )
|
|
{
|
|
fTryOLE = FALSE;
|
|
|
|
if ( ( cb <= *pcb ) &&
|
|
( IsNullPointerVariant( pbData ) ) )
|
|
{
|
|
pbData->vt = VT_EMPTY;
|
|
cb = sizeof( PROPVARIANT );
|
|
}
|
|
|
|
// If we got back VT_EMPTY, it may be because the file has
|
|
// been scanned and not filtered. If there is no write time,
|
|
// the file hasn't been filtered yet, so trying OLE to load
|
|
// the value is worth it.
|
|
|
|
if ( VT_EMPTY == pbData->vt )
|
|
{
|
|
PROPVARIANT vWrite;
|
|
vWrite.vt = VT_EMPTY;
|
|
unsigned cbWrite = sizeof vWrite;
|
|
FetchValue( pidWriteTime, &vWrite, &cbWrite );
|
|
|
|
if ( VT_EMPTY == vWrite.vt )
|
|
fTryOLE = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fTryOLE )
|
|
{
|
|
CImpersonateClient impClient( GetClientToken() );
|
|
|
|
if ( !_propMgr.isOpen() )
|
|
{
|
|
//
|
|
// Get a full, null-terminated, path.
|
|
//
|
|
|
|
CFunnyPath funnyBuf;
|
|
if ( 0 != BuildPath( GetPath(),
|
|
GetName(),
|
|
funnyBuf ) )
|
|
{
|
|
// Open property manager.
|
|
|
|
if ( CImpersonateRemoteAccess::IsNetPath( funnyBuf.GetActualPath() ) )
|
|
{
|
|
UNICODE_STRING const * pVPath = GetVirtualPath();
|
|
|
|
WCHAR const * pwszVPath = 0 != pVPath ? pVPath->Buffer : 0;
|
|
|
|
if ( !_remoteAccess.ImpersonateIfNoThrow( funnyBuf.GetActualPath(),
|
|
pwszVPath ) )
|
|
{
|
|
return CI_E_LOGON_FAILURE;
|
|
}
|
|
}
|
|
else if ( _remoteAccess.IsImpersonated() )
|
|
{
|
|
_remoteAccess.Release();
|
|
}
|
|
|
|
BOOL fSharingViolation = _propMgr.Open( funnyBuf );
|
|
if ( fSharingViolation )
|
|
return CI_E_SHARING_VIOLATION;
|
|
}
|
|
}
|
|
|
|
FULLPROPSPEC const *pPropSpec;
|
|
SCODE sc = _pQueryPropMapper->PropidToProperty( pid, &pPropSpec );
|
|
if ( FAILED( sc ) )
|
|
{
|
|
Win4Assert( !"PropidToProperty failed" );
|
|
|
|
THROW ( CException( sc ) );
|
|
}
|
|
CFullPropSpec const * ps = (CFullPropSpec const *) pPropSpec;
|
|
|
|
cb = *pcb;
|
|
_propMgr.FetchProperty( ps->GetPropSet(),
|
|
ps->GetPropSpec(),
|
|
pbData,
|
|
&cb );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
} // case
|
|
|
|
if ( cb <= *pcb )
|
|
{
|
|
*pcb = cb;
|
|
#if CIDBG == 1
|
|
CStorageVariant var( *pbData );
|
|
|
|
vqDebugOut(( DEB_PROPTIME, "Fetched value (pid = 0x%x): ", pid ));
|
|
var.DisplayVariant( DEB_PROPTIME | DEB_NOCOMPNAME, 0 );
|
|
vqDebugOut(( DEB_PROPTIME | DEB_NOCOMPNAME, "\n" ));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
*pcb = cb;
|
|
vqDebugOut(( DEB_PROPTIME, "Failed to fetch value (pid = 0x%x)\n", pid ));
|
|
sc = CI_E_BUFFERTOOSMALL ;
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
vqDebugOut(( DEB_ERROR,
|
|
"CGenericPropRetriever::RetrieveValueByPid - Exception caught 0x%x\n",
|
|
sc ));
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::StringToVariant, private
|
|
//
|
|
// Arguments: [pString] -- String to copy.
|
|
// [pbData] -- String stored here.
|
|
// [pcb] -- On input: max length in bytes of [pbData].
|
|
// On output: size required by [pString]. If
|
|
// less-than-or-equal-to input size, then string
|
|
// was copied.
|
|
//
|
|
// History: 17-Jul-95 KyleP Created header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CGenericPropRetriever::StringToVariant( UNICODE_STRING const * pString,
|
|
PROPVARIANT * pbData,
|
|
unsigned * pcb )
|
|
{
|
|
unsigned cb = sizeof(PROPVARIANT);
|
|
|
|
if ( 0 == pString || 0 == pString->Length )
|
|
{
|
|
pbData->vt = VT_EMPTY;
|
|
}
|
|
else
|
|
{
|
|
pbData->vt = VT_LPWSTR;
|
|
cb += pString->Length + sizeof( WCHAR ); // For L'\0' at end.
|
|
|
|
if ( cb <= *pcb )
|
|
{
|
|
WCHAR * pwcName = (WCHAR *)PastHeader(pbData);
|
|
pbData->pwszVal = pwcName;
|
|
RtlCopyMemory( pwcName,
|
|
pString->Buffer,
|
|
pString->Length );
|
|
pwcName[pString->Length/sizeof(WCHAR)] = L'\0';
|
|
}
|
|
}
|
|
|
|
*pcb = cb;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::BuildPath, private
|
|
//
|
|
// Synopsis: Gloms path + filename together
|
|
//
|
|
// Arguments: [pPath] -- Path, sans filename
|
|
// [pFilename] -- Filename
|
|
// [funnyBuf] -- Full path copied here.
|
|
//
|
|
// Returns: Size in **bytes** of full path. 0 --> No path
|
|
//
|
|
// History: 04-Jun-98 VikasMan Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
|
|
UNICODE_STRING const * pFilename,
|
|
CFunnyPath & funnyBuf)
|
|
{
|
|
if ( 0 == pPath || 0 == pPath->Length || 0 == pFilename )
|
|
return 0;
|
|
|
|
funnyBuf.SetPath( pPath->Buffer, pPath->Length/sizeof(WCHAR) );
|
|
if ( pFilename->Length > 0 )
|
|
{
|
|
funnyBuf.AppendBackSlash();
|
|
|
|
funnyBuf.AppendPath( pFilename->Buffer, pFilename->Length/sizeof(WCHAR) );
|
|
}
|
|
return funnyBuf.GetLength() * sizeof(WCHAR);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::BuildPath, private
|
|
//
|
|
// Synopsis: Gloms path + filename together
|
|
//
|
|
// Arguments: [pPath] -- Path, sans filename
|
|
// [pFilename] -- Filename
|
|
// [xwcBuf] -- Full path copied here.
|
|
//
|
|
// Returns: Size in **bytes** of full path. 0 --> No path
|
|
//
|
|
// History: 04-Jun-98 VikasMan Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
|
|
UNICODE_STRING const * pFilename,
|
|
XGrowable<WCHAR> & xwcBuf)
|
|
{
|
|
if ( 0 == pPath || 0 == pFilename )
|
|
return 0;
|
|
|
|
unsigned cb = pPath->Length +
|
|
pFilename->Length +
|
|
sizeof WCHAR; // L'\0' at end
|
|
|
|
if ( pFilename->Length > 0 )
|
|
cb += sizeof WCHAR; // L'\\' between path and filename
|
|
|
|
xwcBuf.SetSizeInBytes( cb );
|
|
return BuildPath( pPath, pFilename, xwcBuf.Get(), cb );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::BuildPath, private
|
|
//
|
|
// Synopsis: Gloms path + filename together
|
|
//
|
|
// Arguments: [pPath] -- Path, sans filename
|
|
// [pFilename] -- Filename
|
|
// [pwcBuf] -- Full path copied here.
|
|
// [cbBuf] -- Size in **bytes** of pwcBuf.
|
|
//
|
|
// Returns: Size in **bytes** of full path. Path only built if return
|
|
// value is <= [cbBuf]. 0 --> No path
|
|
//
|
|
// History: 07-Feb-96 KyleP Created header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
|
|
UNICODE_STRING const * pFilename,
|
|
WCHAR * pwcBuf,
|
|
unsigned cbBuf )
|
|
{
|
|
if ( 0 == pPath || 0 == pFilename )
|
|
return 0;
|
|
|
|
unsigned cb = pPath->Length +
|
|
pFilename->Length +
|
|
sizeof WCHAR; // L'\0' at end
|
|
|
|
if ( pFilename->Length > 0 )
|
|
cb += sizeof WCHAR; // L'\\' between path and filename
|
|
|
|
if ( cb <= cbBuf )
|
|
{
|
|
RtlCopyMemory( pwcBuf, pPath->Buffer, pPath->Length );
|
|
pwcBuf += pPath->Length/sizeof(WCHAR);
|
|
|
|
if ( pFilename->Length > 0 )
|
|
{
|
|
*pwcBuf++ = L'\\';
|
|
RtlCopyMemory( pwcBuf,
|
|
pFilename->Buffer,
|
|
pFilename->Length );
|
|
pwcBuf += pFilename->Length / sizeof WCHAR;
|
|
}
|
|
|
|
*pwcBuf = 0;
|
|
}
|
|
|
|
return cb;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::FetchValue, protected
|
|
//
|
|
// Effects: Fetch value from the property cache.
|
|
//
|
|
// Arguments: [pid] -- Property to fetch
|
|
// [pbData] -- Place to return the value
|
|
// [pcb] -- On input, the maximum number of bytes to
|
|
// write at pbData. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// Returns: TRUE if property was fetched
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CGenericPropRetriever::FetchValue( PROPID pid, PROPVARIANT * pbData, unsigned * pcb )
|
|
{
|
|
OpenPropertyRecord();
|
|
|
|
return _cat.FetchValue( _pPropRec, pid, pbData, pcb );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::CheckSecurity
|
|
//
|
|
// Synopsis: Test wid for security access
|
|
//
|
|
// Arguments: [am] -- Access Mask
|
|
// [pfGranted] -- Result of security check returned here
|
|
//
|
|
// History: 19-Aug-93 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CGenericPropRetriever::CheckSecurity( ACCESS_MASK am,
|
|
BOOL *pfGranted)
|
|
{
|
|
//
|
|
// No need to impersonate the client because the Win32 AccessCheck API
|
|
// takes a client token as a parameter
|
|
//
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
if ( _widPrimedForPropRetrieval == widInvalid )
|
|
sc = CI_E_WORKID_NOTVALID;
|
|
else
|
|
{
|
|
OpenPropertyRecord();
|
|
|
|
if ( am != _amAlreadyAccessChecked )
|
|
{
|
|
SDID sdid = _cat.FetchSDID( _pPropRec,
|
|
_widPrimedForPropRetrieval );
|
|
*pfGranted = _secCache.IsGranted( sdid, am );
|
|
}
|
|
else
|
|
*pfGranted = TRUE;
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
vqDebugOut(( DEB_ERROR,
|
|
"CGenericPropRetriever::CheckSecurity - Exception caught 0x%x\n",
|
|
sc ));
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CGenericPropRetriever::EndPropertyRetrieval
|
|
//
|
|
// Synopsis: Reset wid for property retrieval
|
|
//
|
|
// History: 12-Dec-96 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CGenericPropRetriever::EndPropertyRetrieval()
|
|
{
|
|
Win4Assert( _widPrimedForPropRetrieval != widInvalid );
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
Quiesce();
|
|
if ( _remoteAccess.IsImpersonated() )
|
|
_remoteAccess.Release();
|
|
|
|
_widPrimedForPropRetrieval = widInvalid;
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
vqDebugOut(( DEB_ERROR,
|
|
"CGenericPropRetriever::EndPropertyRetrieval - Exception caught 0x%x\n",
|
|
sc ));
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::AddRef
|
|
//
|
|
// Synopsis: Increments refcount
|
|
//
|
|
// History: 12-Dec-1996 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CGenericPropRetriever::AddRef()
|
|
{
|
|
return InterlockedIncrement( (long *) &_cRefs );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::Release
|
|
//
|
|
// Synopsis: Decrement refcount. Delete if necessary.
|
|
//
|
|
// History: 12-Dec-1996 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CGenericPropRetriever::Release()
|
|
{
|
|
Win4Assert( _cRefs > 0 );
|
|
|
|
ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
|
|
|
|
if ( 0 == uTmp )
|
|
delete this;
|
|
|
|
return uTmp;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::QueryInterface
|
|
//
|
|
// Synopsis: Rebind to other interface
|
|
//
|
|
// Arguments: [riid] -- IID of new interface
|
|
// [ppvObject] -- New interface * returned here
|
|
//
|
|
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
|
|
//
|
|
// History: 12-Dec-1996 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CGenericPropRetriever::QueryInterface(
|
|
REFIID riid,
|
|
void ** ppvObject)
|
|
{
|
|
*ppvObject = 0;
|
|
|
|
if ( IID_ICiCPropRetriever == riid )
|
|
*ppvObject = (IUnknown *)(ICiCPropRetriever *)this;
|
|
else if ( IID_IUnknown == riid )
|
|
*ppvObject = (IUnknown *)this;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::FetchPath, protected
|
|
//
|
|
// Synopsis: Reads the path from the open property record
|
|
//
|
|
// Arguments: [pwcPath] -- where to put the path
|
|
// [cwc] -- size of the buffer in/out in characters
|
|
//
|
|
// History: 15-Jan-1998 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CGenericPropRetriever::FetchPath(
|
|
WCHAR * pwcPath,
|
|
unsigned & cwc )
|
|
{
|
|
PROPVARIANT var;
|
|
unsigned cb = cwc * sizeof WCHAR;
|
|
|
|
if ( _cat.FetchValue( GetPropertyRecord(),
|
|
pidPath,
|
|
&var,
|
|
(BYTE *) pwcPath,
|
|
&cb ) )
|
|
cwc = cb / sizeof WCHAR;
|
|
else
|
|
cwc = 0;
|
|
} //FetchPath
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::FixupPath, private
|
|
//
|
|
// Synopsis: Fixes up path (e.g. converts E:\Foo --> \\KyleP-1\RootE\Foo)
|
|
//
|
|
// Arguments: [pwcsPath] -- Source (local) path
|
|
// [pwcsFixup] -- Aliased result
|
|
// [cwcFixup] -- Count of characters in [pwcsFixup].
|
|
//
|
|
// Returns: Count of characters that are in [pwcsFixup]. If return
|
|
// value is larger than [cwcFixup] then nothing was copied.
|
|
//
|
|
// History: 01-Oct-1998 KyleP Created (from ciprop.cxx vroot equivalent)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
unsigned CGenericPropRetriever::FixupPath( WCHAR const * pwcsPath,
|
|
WCHAR * pwcsFixup,
|
|
unsigned cwcFixup )
|
|
{
|
|
BOOL fUseAnyPath = FALSE;
|
|
unsigned cwc = 0;
|
|
|
|
if ( RTScope == _pScope->Type() )
|
|
{
|
|
CScopeRestriction const & scp = * (CScopeRestriction *) _pScope;
|
|
|
|
if ( scp.IsPhysical() )
|
|
{
|
|
BOOL fUnchanged;
|
|
cwc = FetchFixupInScope( pwcsPath,
|
|
pwcsFixup,
|
|
cwcFixup,
|
|
scp.GetPath(),
|
|
scp.PathLength(),
|
|
scp.IsDeep(),
|
|
fUnchanged );
|
|
Win4Assert( cwc > 0 );
|
|
}
|
|
else
|
|
fUseAnyPath = TRUE;
|
|
}
|
|
else if ( RTOr == _pScope->Type() )
|
|
{
|
|
CNodeRestriction const & node = * _pScope->CastToNode();
|
|
|
|
fUseAnyPath = TRUE;
|
|
|
|
for ( ULONG x = 0; x < node.Count(); x++ )
|
|
{
|
|
Win4Assert( RTScope == node.GetChild( x )->Type() );
|
|
|
|
CScopeRestriction const & scp = * (CScopeRestriction *)
|
|
node.GetChild( x );
|
|
|
|
if ( scp.IsPhysical() )
|
|
{
|
|
BOOL fUnchanged;
|
|
cwc = FetchFixupInScope( pwcsPath,
|
|
pwcsFixup,
|
|
cwcFixup,
|
|
scp.GetPath(),
|
|
scp.PathLength(),
|
|
scp.IsDeep(),
|
|
fUnchanged );
|
|
if ( cwc > 0 && !fUnchanged )
|
|
{
|
|
fUseAnyPath = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If no fixup works for the file, use the first match to physical scope.
|
|
//
|
|
|
|
if ( fUseAnyPath )
|
|
cwc = _cat.FixupPath( pwcsPath,
|
|
pwcsFixup,
|
|
cwcFixup,
|
|
0 );
|
|
|
|
return cwc;
|
|
} //FixupPath
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CGenericPropRetriever::FetchFixupInScope, private
|
|
//
|
|
// Synopsis: Worker subroutine for FixupPath
|
|
//
|
|
// Arguments: [pwcsPath] -- Source (local) path
|
|
// [pwcsFixup] -- Aliased result
|
|
// [cwcFixup] -- Count of characters in [pwcsFixup].
|
|
// [pwcRoot] -- Root scope (must match alias)
|
|
// [cwcRoot] -- Size (in chars) of [pwcRoot]
|
|
// [fDeep] -- True if [pwcRoot] is a deep scope.
|
|
//
|
|
// Returns: Count of characters that are in [pwcsFixup]. If return
|
|
// value is larger than [cwcFixup] then nothing was copied.
|
|
//
|
|
// History: 01-Oct-1998 KyleP Created (from ciprop.cxx vroot equivalent)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
unsigned CGenericPropRetriever::FetchFixupInScope( WCHAR const * pwcsPath,
|
|
WCHAR * pwcsFixup,
|
|
unsigned cwcFixup,
|
|
WCHAR const * pwcRoot,
|
|
unsigned cwcRoot,
|
|
BOOL fDeep,
|
|
BOOL & fUnchanged )
|
|
{
|
|
fUnchanged = FALSE;
|
|
CScopeMatch Match( pwcRoot, cwcRoot );
|
|
unsigned cSkip = 0;
|
|
unsigned cwcPath = 0;
|
|
unsigned cwcMaxPath = 0; // Used to hold longest path (when cwcFixup == 0)
|
|
|
|
unsigned cwcOriginalPath = wcslen( pwcsPath );
|
|
|
|
while ( TRUE )
|
|
{
|
|
cwcPath = _cat.FixupPath( pwcsPath,
|
|
pwcsFixup,
|
|
cwcFixup,
|
|
cSkip );
|
|
|
|
if ( 0 == cwcPath )
|
|
return cwcMaxPath;
|
|
|
|
//
|
|
// If no fixups matched, return the original path
|
|
//
|
|
|
|
if ( cwcPath == cwcOriginalPath &&
|
|
RtlEqualMemory( pwcsPath, pwcsFixup, cwcPath * sizeof WCHAR ) )
|
|
{
|
|
fUnchanged = TRUE;
|
|
return cwcPath;
|
|
}
|
|
|
|
//
|
|
// In scope?
|
|
//
|
|
|
|
if ( cwcPath > cwcFixup || !Match.IsInScope( pwcsFixup, cwcFixup ) )
|
|
{
|
|
cSkip++;
|
|
|
|
//
|
|
// Update max fixup size if we're polling for space requirements.
|
|
//
|
|
|
|
if ( cwcPath > cwcFixup && cwcPath > cwcMaxPath )
|
|
cwcMaxPath = cwcPath;
|
|
|
|
continue;
|
|
}
|
|
|
|
Win4Assert( 0 == pwcsFixup[cwcPath] );
|
|
|
|
//
|
|
// If the scope is shallow, check that it's still in scope
|
|
//
|
|
|
|
if ( !fDeep )
|
|
{
|
|
unsigned cwcName = 0;
|
|
WCHAR * pwcName = pwcsFixup + cwcPath - 1;
|
|
|
|
while ( L'\\' != *pwcName )
|
|
{
|
|
Win4Assert( cwcName < cwcPath );
|
|
cwcName++;
|
|
pwcName--;
|
|
}
|
|
|
|
unsigned cwcJustPath = cwcPath - cwcName - 1;
|
|
|
|
BOOL fTooDeep = cwcJustPath > cwcRoot;
|
|
|
|
if ( fTooDeep )
|
|
{
|
|
cSkip++;
|
|
continue;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (0 == cwcMaxPath)
|
|
return cwcPath;
|
|
else
|
|
return cwcMaxPath;
|
|
} //FetchFixupInScope
|
|
|