WindowsXP-SP1/windows/oleacc/oleacc/propmgr_client.cpp
2020-09-30 16:53:49 +02:00

388 lines
12 KiB
C++

// Copyright (c) 2000-2000 Microsoft Corporation
// --------------------------------------------------------------------------
//
// PropMgr_Client
//
// Property manager / annotation client. Uses the shared memory component
// (PropMgr_MemStream.*) to read properties directly w/o cross-proc com overhead
// to the annotation server.
//
// This is effectively a singleton - Init/Uninit called at startup/shutdown,
// plus one method to get properties.
//
// --------------------------------------------------------------------------
#include "oleacc_p.h"
#include "PropMgr_Client.h"
#include "PropMgr_Util.h"
#include "PropMgr_Mem.h"
// Note: See PropMgr_Impl.cpp for a description of the shared memory
// layout.
// class MapReaderMgr
//
// This class manages looking up properties.
//
// This class is private to this file; its functionality is exposed by the
// PropMgr_ APIs near the bottom of this file.
//
// This class is a singleton, a single instance, g_MapReader, exists.
class MapReaderMgr
{
// _ReadCallbackProperty
//
// Given a pointer to the start of a marshaled object reference pInfo,
// it unmarshalls the callback object and calls it to get the property
// corresponding to the given child key.
// Returns TRUE if all goes well, and if the callback knows about this
// property.
BOOL _ReadCallbackProperty( MemStream pInfo,
const BYTE * pChildKey, DWORD dwChildKeyLen,
PROPINDEX idxProp,
VARIANT * pvar )
{
// Read length of marshalled data...
DWORD dwLen;
if( ! MemStreamRead_DWORD( pInfo, & dwLen ) )
{
return FALSE;
}
const BYTE * pData = MemStream_GetBinaryPtr( pInfo, dwLen );
if( ! pData )
{
return FALSE;
}
IAccPropServer * pServer = NULL;
HRESULT hr = UnmarshalInterface( pData, dwLen, IID_IAccPropServer, (void **) & pServer );
if( hr != S_OK )
{
return FALSE;
}
// Got it - ask it for the property...
BOOL fGotProp = FALSE;
hr = pServer->GetPropValue( pChildKey, dwChildKeyLen,
*g_PropInfo[ idxProp ].m_idProp,
pvar,
& fGotProp );
pServer->Release();
// Did the call succeed, and did the server return a value?
if( hr != S_OK || fGotProp == FALSE )
{
return FALSE;
}
return TRUE;
}
// Read a specific property from a record .
// (a record contains all properties about a given object)
BOOL _ReadPropertyFromEntry( MemStream pEntryInfo,
const BYTE * pChildKey, DWORD dwChildKeyLen,
PROPINDEX idxProp,
BOOL fWantContainerOnly,
VARIANT * pvar )
{
// Skip over the size at start of info block
if( ! MemStreamSkip_DWORD( pEntryInfo ) )
{
return FALSE;
}
// Extract the bitmasks:
// Which properties are present, which are variants, and which are scoped...
DWORD dwUsedBits;
DWORD dwVariantBits;
DWORD dwScopeBits;
if( ! MemStreamRead_DWORD( pEntryInfo, & dwUsedBits )
|| ! MemStreamRead_DWORD( pEntryInfo, & dwVariantBits )
|| ! MemStreamRead_DWORD( pEntryInfo, & dwScopeBits ) )
{
return FALSE;
}
// Is the property we're looking for present at all?
// (Note - if we decide to allow other GUIDS other than those in the array,
// we'll have to skip over the indexed ones and then search through any
// guid/val pairs after that. Could use one bit of this mask to indicate
// 'there are other // GUID properties present', though.)
if( ! IsBitSet( dwUsedBits, idxProp ) )
{
// Property not present - return false.
return FALSE;
}
// The property is present - but are we specifically looking for
// container-scoped properties? If so, bail out if the bit isn't set...
if( fWantContainerOnly && ! IsBitSet( dwScopeBits, idxProp ) )
{
return FALSE;
}
// Property is present - now we have to skip over the other present
// properties to get to the one we want...
for( int i = 0 ; i < idxProp ; i++ )
{
// Only haqve to skip over properties that are actually present...
if( IsBitSet( dwUsedBits, i ) )
{
if( IsBitSet( dwVariantBits, i ) )
{
// Skip over variant...
if( ! MemStreamSkip_VARIANT( pEntryInfo ) )
return FALSE;
}
else
{
// Skip over object reference...
DWORD dwLen;
if( ! MemStreamRead_DWORD( pEntryInfo, & dwLen ) )
return FALSE;
if( ! MemStreamSkip_Binary( pEntryInfo, dwLen ) )
return FALSE;
}
}
}
// Now we're at the one we want. Extract it...
// Is it a variant or a server object?
if( IsBitSet( dwVariantBits, idxProp ) )
{
// variant - return it...
return MemStreamRead_VARIANT( pEntryInfo, pvar );
}
else
{
// server object - use and return what it returns...
return _ReadCallbackProperty( pEntryInfo,
pChildKey, dwChildKeyLen,
idxProp,
pvar );
}
}
HWND PropHwndFromKey( const BYTE * pKey, DWORD dwKeyLen )
{
HWND hwndProp;
if( DecodeHwndKey( pKey, dwKeyLen, & hwndProp, NULL, NULL ) )
{
return hwndProp;
}
// If it's a HMENU key, find the PID, then find window using window name
// generated using that PID...
DWORD dwPid;
if( DecodeHmenuKey( pKey, dwKeyLen, & dwPid, NULL, NULL ) )
{
TCHAR szWindowName[ 64 ];
wsprintf( szWindowName, TEXT("MSAA_DA_%lx"), dwPid );
hwndProp = FindWindow( TEXT("MSAA_DA_Class"), szWindowName );
return hwndProp;
}
return NULL;
}
// _LookupProp
//
//
// fWantContainerOnly means we're only interested in props markes with the
// 'container' scope. This happens when we search for a prop for a child,
// don't find anything there - so also check parent to see if it is a parent
// and has a property set for it and its children. (These props are currently
// always server callback props)
BOOL _LookupProp( const BYTE * pKey, DWORD dwKeyLen,
const BYTE * pChildKey, DWORD dwChildKeyLen,
PROPINDEX idxProp, BOOL fWantContainerOnly, VARIANT * pvar )
{
HWND hwndProp = PropHwndFromKey( pKey, dwKeyLen );
if( ! hwndProp )
{
return FALSE;
}
LPTSTR pKeyString = MakeKeyString( pKey, dwKeyLen );
if( ! pKeyString )
{
return FALSE;
}
void * pvProp = GetProp( hwndProp, pKeyString );
delete [ ] pKeyString;
if( ! pvProp )
{
return FALSE;
}
DWORD pid = 0;
GetWindowThreadProcessId( hwndProp, & pid );
if( ! pid )
{
return FALSE;
}
HANDLE hProcess = OpenProcess( PROCESS_VM_READ, FALSE, pid );
if( ! hProcess )
{
return FALSE;
}
DWORD dwSize;
SIZE_T cbBytesRead = 0;
if( ! ReadProcessMemory( hProcess, pvProp, & dwSize, sizeof( dwSize ), & cbBytesRead )
|| cbBytesRead != sizeof( dwSize ) )
{
CloseHandle( hProcess );
return FALSE;
}
BYTE * pBuffer = new BYTE [ dwSize ];
if( ! pBuffer )
{
CloseHandle( hProcess );
return FALSE;
}
cbBytesRead = 0;
if( ! ReadProcessMemory( hProcess, pvProp, pBuffer, dwSize, & cbBytesRead )
|| cbBytesRead != dwSize )
{
delete [ ] pBuffer;
CloseHandle( hProcess );
return FALSE;
}
CloseHandle( hProcess );
MemStream p( pBuffer, dwSize );
BOOL fGotProp = _ReadPropertyFromEntry( p,
pChildKey, dwChildKeyLen,
idxProp,
fWantContainerOnly,
pvar );
delete [ ] pBuffer;
return fGotProp;
}
public:
BOOL LookupProp( const BYTE * pKey,
DWORD dwKeyLen,
PROPINDEX idxProp,
VARIANT * pvar )
{
BOOL bRetVal = _LookupProp( pKey, dwKeyLen,
pKey, dwKeyLen,
idxProp, FALSE, pvar );
if( ! bRetVal )
{
// Is this a leaf-node element? If so, try the parent for a 'container
// scope' property.
// This is what allows a callback-annotation on a parent to apply
// to all its simple-element children
// If we later extend this to allow for pluggable namespaces, we'd
// need to change this to be non-HWND-specific (eg. call a
// IAccNamespece::GetParentKey() or similar method)
HWND hwnd;
DWORD idObject;
DWORD idChild;
if( DecodeHwndKey( pKey, dwKeyLen, & hwnd, & idObject, & idChild )
&& idChild != CHILDID_SELF )
{
BYTE ParentKey[ HWNDKEYSIZE ];
MakeHwndKey( ParentKey, hwnd, idObject, CHILDID_SELF );
bRetVal = _LookupProp( ParentKey, HWNDKEYSIZE,
pKey, dwKeyLen,
idxProp, TRUE, pvar );
}
else
{
HMENU hmenu;
DWORD idChild;
DWORD dwpid;
if( DecodeHmenuKey( pKey, dwKeyLen, & dwpid, & hmenu, & idChild )
&& idChild != CHILDID_SELF )
{
BYTE ParentKey[ HMENUKEYSIZE ];
MakeHmenuKey( ParentKey, dwpid, hmenu, CHILDID_SELF );
bRetVal = _LookupProp( ParentKey, HMENUKEYSIZE,
pKey, dwKeyLen,
idxProp, TRUE, pvar );
}
}
}
return bRetVal;
}
};
MapReaderMgr g_MapReader;
BOOL PropMgrClient_Init()
{
// no-op
return TRUE;
}
void PropMgrClient_Uninit()
{
// no-op
}
BOOL PropMgrClient_CheckAlive()
{
// no-op
return TRUE;
}
BOOL PropMgrClient_LookupProp( const BYTE * pKey,
DWORD dwKeyLen,
PROPINDEX idxProp,
VARIANT * pvar )
{
return g_MapReader.LookupProp( pKey, dwKeyLen, idxProp, pvar );
}