windows-nt/Source/XPSP1/NT/inetsrv/query/icommand/svcquery.cxx
2020-09-26 16:20:57 +08:00

325 lines
9.8 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: SvcQuery.cxx
//
// Contents: IInternalQuery interface for cisvc
//
// History: 13-Sep-96 dlee Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <restrict.hxx>
#include <rowset.hxx>
#include <query.hxx>
#include <pidmap.hxx>
#include <coldesc.hxx>
#include <lang.hxx>
#include <rstprop.hxx>
#include <proprst.hxx>
#include "svcquery.hxx"
//+-------------------------------------------------------------------------
//
// Member: CSvcQuery::QueryInterface, public
//
// Arguments: [ifid] -- Interface id
// [ppiuk] -- Interface return pointer
//
// Returns: Error. No rebind from this class is supported.
//
// History: 13-Sep-96 dlee Created
//
//--------------------------------------------------------------------------
STDMETHODIMP CSvcQuery::QueryInterface(
REFIID ifid,
void ** ppiuk )
{
if ( IID_IUnknown == ifid )
{
AddRef();
*ppiuk = (void *)((IUnknown *)this);
return S_OK;
}
else
{
*ppiuk = 0;
return E_NOINTERFACE;
}
} //QueryInterface
//+-------------------------------------------------------------------------
//
// Member: CSvcQuery::AddRef, public
//
// Synopsis: Reference the virtual table.
//
// History: 13-Sep-96 dlee Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CSvcQuery::AddRef()
{
return InterlockedIncrement( (long *) &_ref );
} //AddRef
//+-------------------------------------------------------------------------
//
// Member: CSvcQuery::Release, public
//
// Synopsis: De-Reference the virtual table.
//
// Effects: If the ref count goes to 0 then the table is deleted.
//
// History: 13-Sep-96 dlee Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CSvcQuery::Release()
{
long l = InterlockedDecrement( (long *) &_ref );
if ( l <= 0 )
{
// delete self
vqDebugOut(( DEB_ITRACE,
"Svc IInternalQuery unreferenced. Deleting.\n" ));
delete this;
return 0;
}
return l;
} //Release
//+-------------------------------------------------------------------------
//
// Class: CCursorArray
//
// Synopsis: Smart container of query cursors
//
// History: 16-Feb-97 dlee Created
//
//--------------------------------------------------------------------------
class CCursorArray
{
public:
CCursorArray( ULONG * pCursors,
ULONG cCursors,
CSvcQueryProxy & Query ) :
_pCursors( pCursors ),
_cCursors( cCursors ),
_Query( Query )
{
}
void Acquire( ULONG iElement )
{
_pCursors[ iElement ] = 0;
}
~CCursorArray()
{
// FreeCursor can fail if the pipe is stale, in which
// case don't bother with freeing the rest of the cursors.
TRY
{
for ( ULONG x = 0; x < _cCursors; x++ )
{
if ( 0 != _pCursors[ x ] )
_Query.FreeCursor( _pCursors[ x ] );
}
}
CATCH( CException, e )
{
}
END_CATCH
}
private:
ULONG * _pCursors;
ULONG _cCursors;
CSvcQueryProxy & _Query;
};
//+-------------------------------------------------------------------------
//
// Member: CSvcQuery::Execute, public
//
// Synopsis: Executes a query. Helper for ICommand::Execute.
//
// Arguments: [pUnkOuter] -- Outer unknown
// [pRestriction] -- Query restriction
// [pidmap] -- pid mapper for output, sort, category columns
// [rColumns] -- Output columns in IRowset
// [rSort] -- Initial sort
// [xProps] -- Rowset properties (query flags)
// [rCateg] -- Categorization specification
// [cRowsets] -- # of rowsets
// [ppUnknowns] -- IUnknowns returned here
// [aAccessors] -- Bag of accessors which rowsets need to inherit
//
// Returns: Throws on error
//
// History: 26 Nov 1995 AlanW Created
// 13-Sep-96 dlee Make it support cisvc
//
//--------------------------------------------------------------------------
void CSvcQuery::Execute( IUnknown * pUnkOuter,
RESTRICTION * pRestriction,
CPidMapperWithNames & pidmap,
CColumnSet & rColumns,
CSortSet & rSort,
XPtr<CMRowsetProps> & xProps,
CCategorizationSet & rCateg,
ULONG cRowsets,
IUnknown ** ppUnknowns,
CAccessorBag & aAccessors,
IUnknown * pUnkCreator )
{
if (0 == ppUnknowns)
THROW(CException( E_INVALIDARG));
if ( cRowsets != 1 + (rCateg.Count() ? rCateg.Count() : 0) )
THROW( CException( E_INVALIDARG ));
if (_QueryUnknown.IsQueryActive())
{
vqDebugOut(( DEB_ERROR,
"CSvcQuery: Query already active.\n" ));
// NTRAID#DB-NTBUG9-84330-2000/07/31-dlee OLE-DB spec variance in Indexing Service when reexecuting queries
// spec variance: only if query changed
THROW( CException( DB_E_OBJECTOPEN ));
}
// Construct table
*ppUnknowns = 0; // in case of error or exception
XArray<ULONG> aCursors( cRowsets );
// Construct a CRowsetProperties
CRowsetProperties Prop;
Prop.SetDefaults( xProps->GetPropertyFlags(),
xProps->GetMaxOpenRows(),
xProps->GetMemoryUsage(),
xProps->GetMaxResults(),
xProps->GetCommandTimeout(),
xProps->GetFirstRows() );
XInterface<CSvcQueryProxy> xQuery(new
CSvcQueryProxy( _client,
rColumns,
(CRestriction&) (*pRestriction),
rSort.Count() ? &rSort : 0,
rCateg.Count() ? &rCateg : 0,
Prop,
pidmap,
cRowsets,
aCursors.GetPointer()
));
// Make rowsets for each level in the hierarchy (usually 1).
// Rowset 0 is the top of the hierarchy.
CCursorArray cursorArray( aCursors.GetPointer(),
cRowsets,
xQuery.GetReference() );
_QueryUnknown.ReInit();
CRowsetArray apRowsets( cRowsets );
XArray<IUnknown *> xapUnknown( cRowsets );
CMRowsetProps & OrigProps = xProps.GetReference();
for ( unsigned r = 0; r < cRowsets; r++ )
{
// First rowset is not chaptered, even if others are.
XPtr<CMRowsetProps> xTmp;
if ( 0 != r )
{
xTmp.Set( new CMRowsetProps( OrigProps ) );
xTmp->SetChaptered( TRUE );
}
if ( 1 != cRowsets && 0 == r )
xProps->SetChaptered( FALSE );
apRowsets[r] = new CRowset( pUnkOuter,
&xapUnknown[r],
(r == (cRowsets - 1)) ?
rColumns :
rCateg.Get(r)->GetColumnSet(),
pidmap,
xQuery.GetReference(),
(IUnknown &) _QueryUnknown,
0 != r,
( 0 == r ) ? xProps : xTmp,
aCursors[r],
aAccessors,
pUnkCreator );
// the cursor is acquired
cursorArray.Acquire( r );
}
for (r = 0; r < cRowsets; r++)
{
if (r < cRowsets-1)
apRowsets[r]->SetRelatedRowset( apRowsets[r+1] );
ppUnknowns[r] = xapUnknown[r];
}
// xQuery goes out of scope, which does a Release() on it.
// Each rowset above has done an AddRef() on it and they own it.
// ReInit can't fail
_QueryUnknown.ReInit( cRowsets, apRowsets.Acquire() );
} //Execute
//+-------------------------------------------------------------------------
//
// Member: CSvcQuery::CSvcQuery, public
//
// Synopsis: saves the query scope, machine, and catalog
//
// Arguments: [cScopes] - # of entries in the scope arrays
// [aDepths] - array of scope depths
// [aScopes] - array of paths to roots of scopes
// [pwcCatalog] - catalog override name or path
// [pwcMachine] - Machine name for catalog
//
// History: 13-Sep-96 dlee Updated from FAT for svc
//
//--------------------------------------------------------------------------
CSvcQuery::CSvcQuery(
WCHAR const * pwcMachine,
IDBProperties * pDbProperties ) :
#pragma warning(disable : 4355) // 'this' in a constructor
_QueryUnknown( * ((IUnknown *) this) ),
#pragma warning(default : 4355) // 'this' in a constructor
PIInternalQuery( 0 ),
_client( pwcMachine, pDbProperties )
{
AddRef();
} //CSvcQuery