///////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// @module ROWSET.H | CRowset base object and contained interface
// 
//
///////////////////////////////////////////////////////////////////////////////////

#ifndef _ROWSET_H_
#define _ROWSET_H_

#include "baserowobj.h"
#include "bitarray.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define COLUMNINFO_SIZE MAX_PATH*3
#define DEFAULT_COLUMNS_TO_ADD 100
/////////////////////////////////////////////////////////////////////////////////////////////////////

#define COLUMNSTAT_MODIFIED		0x1000
#define NOCOLSCHANGED			0x0010

class CImpIAccessor;
class CImpIGetRow;
class CImplIRowsetRefresh;
class CImplIParentRowset;
class CQuery;
class CCommand;

typedef CImpIGetRow			 *	PIMPIGETROW;
typedef CImplIRowsetRefresh  *	PIMPIROWSETREFRESH;
typedef CHashTbl			 *	PHASHTBL;
typedef	CCommand			 *	PCCOMMAND;



///////////////////////////////////////////////////////////////////////////////////////////////////////
class CRowset : public CBaseRowObj				
{
	//	Contained interfaces are friends
	friend class CImpIRowsetLocate;
	friend class CImpIRowsetChange;
	friend class CImpIRowsetIdentity;
	friend class CImpIRowsetInfo;
	friend class CImpIAccessor;
	friend class CImpIGetRow;
	friend class CImplIRowsetRefresh;
	friend class CImpIChapteredRowset;

	friend class CRowFetchObj;
	friend class CInstanceRowFetchObj;
	friend class CQualifierRowFetchObj;
	friend class CRow;

    private: 

		CWMIInstanceMgr	*				m_InstMgr;						// to manage pointer to instance to HROW

		                       
		PIMPIROWSET						m_pIRowset;                     // Contained IRowset
		PIMPIROWSETLOCATE				m_pIRowsetLocate;               // Contained IRowsetLocate
		PIMPIROWSETCHANGE				m_pIRowsetChange;				// Contained IRowsetChange
		PIMPIROWSETIDENTITY				m_pIRowsetIdentity;             // Contained IRowsetIdentity
        PIMPIACCESSOR					m_pIAccessor;                   // Contained IAccessor
		PICHAPTEREDROWSET				m_pIChapteredRowset;			// Contained IChapteredRowset
		PIMPIROWSETINFO					m_pIRowsetInfo;					// Contained IRowsetInfo;
		PIMPIGETROW						m_pIGetRow;						// contained IGetRow
		PIMPIROWSETREFRESH				m_pIRowsetRefresh;				// Contained IRowsetIdentity
		PROWFETCHOBJ					m_pRowFetchObj;					// Rowfetch Object to fetch rows
		PHASHTBL						m_pHashTblBkmark;				// HashTable pointer to store bookmarks

		PCCOMMAND						m_pParentCmd;					// Command object which created the rowset

		DBORDINAL          				m_irowMin;                      // index of the first available rowbuffer
		ULONG_PTR          				m_cRows;                        // current # of rows in the buffer

		DBSTATUS          				m_dwStatus;                     // status word for the entire cursor
		BYTE*							m_pLastBindBase;                // remember last binding location
		DBROWCOUNT         				m_ulRowRefCount;	            // RefCount of all outstanding row handles
//		HCHAPTER						m_hLastChapterAllocated;		// variable to store the last HCHAPTER given;
		HCHAPTER						m_hLastChapterAllocated;		// variable to store the last HCHAPTER given;


		
		BOOL							m_bHelperFunctionCreated;		// flag to indicate whethe helper function are created or not
		HROW							m_ulLastFetchedRow;				// Position of the last fetched Row

																		// retrieved from WMIOLEDBMAP class or not
		HROW							m_hRowLastFetched;				// last fetched HROW

		CBaseRowObj **					m_ppChildRowsets;				// Array of rowset pointers for child recordsets
		BSTR							m_strPropertyName;				// Name of the property for which Qualifier is
            															// is to be retrieved
		CWbemClassWrapper *				m_pInstance;					// Instance pointer of instance for which this qualifier
																	// rowset is pointing
		BOOL							m_bIsChildRs;					// flag indicating whether the rowset is a child rowset

		FETCHDIRECTION					m_FetchDir;						// The last fetch Direction;
		ULONG_PTR						m_lLastFetchPos;				// The last fetched position
		DBCOUNTITEM						m_lRowCount;					// The number of rows in rowset


		HRESULT		GatherColumnInfo(void);         	                	//Builds DBCOLINFO structures
		HRESULT		ReleaseAllRows();										// release all rows during desctuction	
		HRESULT		CreateHelperFunctions(void);       	                	//Creates Helper Classes 
		ROWBUFF*	GetRowBuff(HROW iRow, BOOL fDataLocation = FALSE);    //Returns the Buffer Pointer for the specified row identified from HROW
		ROWBUFF*	GetRowBuffFromSlot(HSLOT hSlot, BOOL fDataLocation = FALSE);    //Returns the Buffer Pointer for the specified row identified by slot
		HRESULT		Rebind(BYTE* pBase);                               		//Establishes the data area bindings
		HRESULT		ReleaseRowData(HROW hRow,BOOL bReleaseSlot = TRUE);

		HRESULT		ResetInstances();                                   // Set instance back to 0
		HRESULT		ResetQualifers(HCHAPTER hChapter);
        HRESULT		ResetRowsetToNewPosition(DBROWOFFSET lRowOffset,CWbemClassWrapper *pInst = NULL);      // Start getting at new position

		HRESULT		AllocateAndInitializeChildRowsets();				// ALlocate and initialize rowsets for child recordsets
		HRESULT		GetChildRowset(DBORDINAL ulOrdinal,REFIID riid ,IUnknown ** ppIRowset);		// get the pointer to the child recordsets



		HRESULT		CheckAndInitializeChapter(HCHAPTER hChapter);

        HRESULT		GetNextInstance(CWbemClassWrapper *&ppInst, CBSTR &strKey,BOOL bFetchBack);					// Get the next one in the list
		HRESULT		GetNextPropertyQualifier(CWbemClassWrapper *pInst,BSTR strPropName,BSTR &strQualifier,BOOL bFetchBack);
		HRESULT		GetInstanceDataToLocalBuffer(CWbemClassWrapper *pInst,HSLOT hSlot,BSTR strQualifer = Wmioledb_SysAllocString(NULL));			// Get the Instance Data and put it into the
																		// provider's own memory
		HRESULT		GetNextClassQualifier(CWbemClassWrapper *pInst,BSTR &strQualifier,BOOL bFetchBack);
		HRESULT		ReleaseInstancePointer(HROW hRow);						// function to relese HROW from the chapter manager
																		// and instance manager when row is released
		
		BOOL		IsRowExists(HROW hRow);
		HRESULT		IsSlotSet(HSLOT hRow);
		HSLOT		GetSlotForRow(HROW hRow);
        
        HRESULT		SetRowsetProperties(const ULONG cPropertySets, const DBPROPSET	rgPropertySets[] );
		HRESULT		GetData(HROW hRow ,BSTR strQualifer = Wmioledb_SysAllocString(NULL));
		HRESULT		UpdateRowData(HROW hRow,PACCESSOR pAccessor, BOOL bNewInst);
		HRESULT		DeleteRow(HROW hRow,DBROWSTATUS * pRowStatus);
		void		SetRowStatus(HROW hRow , DBSTATUS dwStatus);
		DBSTATUS	GetRowStatus(HROW hRow);
		void		GetInstanceKey(HROW hRow , BSTR *strKey);
		HRESULT		UpdateRowData(HROW hRow,DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ]);
		void		SetStatus(HCHAPTER hChapter , DWORD dwStatus);
		DBSTATUS	GetStatus(HCHAPTER hChapter = 0);
		HRESULT		InsertNewRow(CWbemClassWrapper **ppNewInst);
		HRESULT		GetColumnInfo(DBORDINAL* pcColumns, DBCOLUMNINFO** prgInfo,WCHAR** ppStringsBuffer);
		void		GetBookMark(HROW hRow,BSTR &strBookMark);
		HRESULT		FillHChaptersForRow(CWbemClassWrapper *pInst, BSTR strKey);
//		HCHAPTER	GetNextHChapter() { return ++m_hLastChapterAllocated; }
		HCHAPTER	GetNextHChapter() { return ++m_hLastChapterAllocated; }
		HRESULT		AddRefChapter(HCHAPTER hChapter,DBREFCOUNT * pcRefCount);
		HRESULT		ReleaseRefChapter(HCHAPTER hChapter,DBREFCOUNT * pcRefCount);	// Release reference to chapter
		HRESULT		GetRowCount();
		HRESULT		GetDataToLocalBuffer(HROW hRow);
		BOOL		IsInstanceDeleted(CWbemClassWrapper *pInst);
		HRESULT		AllocateInterfacePointers();
		void		InitializeRowsetProperties();
		HRESULT		AddInterfacesForISupportErrorInfo();

		CWbemClassWrapper * GetInstancePtr(HROW hRow);
		INSTANCELISTTYPE	GetObjListType()	{ return m_pMap->GetObjListType(); }

		FETCHDIRECTION	 GetCurFetchDirection() { return m_pMap->GetCurFetchDirection(); }
		void	 SetCurFetchDirection(FETCHDIRECTION FetchDir);
	
	public:

		 // For Hierarchical recordset to represent Qualifiers
		CRowset(LPUNKNOWN pUnkOuter,ULONG uQType, LPWSTR PropertyName,PCDBSESSION pObj , CWmiOleDBMap *pMap);
		CRowset(LPUNKNOWN pUnkOuter,PCDBSESSION pObj ,CWbemConnectionWrapper *pCon = NULL);


		~CRowset(void);
        void InitVars();
		
        inline BOOL BitArrayInitialized();
        inline LPEXTBUFFER GetAccessorBuffer();

    	inline PCUTILPROP GetCUtilProp() { return m_pUtilProp; };       // Return the CUtilProp object
		CWmiOleDBMap *GetWmiOleDBMap() { return m_pMap; };

		// Initialization functions
		
		HRESULT InitRowset( const ULONG		    cPropertySets, 
			                const DBPROPSET		rgPropertySets[] );

		// overloaded function for rowsets resulted from executing
		// query from command object
		HRESULT InitRowset( const ULONG cPropertySets, 
							const DBPROPSET	rgPropertySets[],
							DWORD dwFlags, 
							CQuery* p,
							PCCOMMAND pCmd );

		// Overloaded function for normal rowset and schema rowsets
        HRESULT InitRowset( int nBaseType,const ULONG cPropertySets, const DBPROPSET	rgPropertySets[],LPWSTR TableID, DWORD dwFlags, LPWSTR SpecificTable );

        HRESULT InitRowset( const ULONG cPropertySets, 
							const DBPROPSET	rgPropertySets[],
							LPWSTR TableID,
							BOOL fSchema = FALSE, 
							DWORD dwFlags = -1 );

		HRESULT InitRowset( const ULONG cPropertySets, 
							const DBPROPSET	rgPropertySets[],
							LPWSTR strObjectID,
							LPWSTR strObjectToOpen,
							INSTANCELISTTYPE objInstListType , 
							DWORD dwFlags = -1);
		
		HRESULT InitRowsetForRow(	LPUNKNOWN pUnkOuter ,
									const ULONG cPropertySets, 
									const DBPROPSET	rgPropertySets[] , 
									CWbemClassWrapper *pInst);
		
        void GetQualiferName(HROW hRow,BSTR &strBookMark);

		// IUnknown methods
		STDMETHODIMP			QueryInterface(REFIID, LPVOID *);
		STDMETHODIMP_(ULONG)	AddRef(void);
		STDMETHODIMP_(ULONG)	Release(void);
	
		
};

typedef CRowset *PCROWSET;

////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIRowsetLocate : public IRowsetLocate		
{
	private:
		DEBUGCODE(ULONG m_cRef);											
		CRowset	 *		m_pObj;	

	public: 
		CImpIRowsetLocate( CRowset *pObj )				
		{																
			DEBUGCODE(m_cRef = 0L);										
			m_pObj		= pObj;											
		}																
		~CImpIRowsetLocate()													
		{											
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP	GetData(HROW, HACCESSOR, void*);
		STDMETHODIMP	GetNextRows(HCHAPTER, DBROWOFFSET, DBROWCOUNT, DBCOUNTITEM*, HROW**);
		STDMETHODIMP	ReleaseRows(DBCOUNTITEM, const HROW[], DBROWOPTIONS[], DBREFCOUNT[], DBROWSTATUS[]);
		STDMETHODIMP	RestartPosition(HCHAPTER);
        STDMETHODIMP	AddRefRows(DBCOUNTITEM, const HROW[], DBREFCOUNT[], DBROWSTATUS[]);

		// IRowsetLocate Methods
		STDMETHODIMP	Compare (HCHAPTER       hChapter,
								 DBBKMARK          cbBookmark1,
								 const BYTE *   pBookmark1,
								 DBBKMARK          cbBookmark2,
								 const BYTE *   pBookmark2,
								 DBCOMPARE *    pComparison);

		STDMETHODIMP	GetRowsAt (HWATCHREGION   hReserved1,
								   HCHAPTER       hChapter,
								   DBBKMARK       cbBookmark,
								   const BYTE *   pBookmark,
								   DBROWOFFSET    lRowsOffset,
								   DBROWCOUNT     cRows,
								   DBCOUNTITEM *  pcRowsObtained,
								   HROW **        prghRows);


		STDMETHODIMP	GetRowsByBookmark (HCHAPTER       hChapter,
										   DBCOUNTITEM    cRows,
										   const DBBKMARK rgcbBookmarks[],
										   const BYTE *   rgpBookmarks[],
										   HROW           rghRows[],
										   DBROWSTATUS    rgRowStatus[]);


		STDMETHODIMP	Hash (HCHAPTER       hChapter,
							   DBBKMARK      cBookmarks,
							   const DBBKMARK rgcbBookmarks[],
							   const BYTE *   rgpBookmarks[],
							   DBHASHVALUE    rgHashedValues[],
							   DBROWSTATUS    rgBookmarkStatus[]);



		// a utility function
        HRESULT CheckParameters(DBCOUNTITEM * pcRowsObtained,  DBROWOFFSET lRowOffset,  DBROWCOUNT  cRows,HROW **prghRows );

};

///////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIRowsetChange : public IRowsetChange	
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

	public: 
		
		CImpIRowsetChange( CRowset *pObj )			
		{																
			DEBUGCODE(m_cRef = 0L);										
			m_pObj		= pObj;											
		}																
		~CImpIRowsetChange()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

	    STDMETHODIMP	SetData(HROW, HACCESSOR, void*);
	    STDMETHODIMP	DeleteRows(HCHAPTER, DBCOUNTITEM, const HROW[], DBROWSTATUS[]);
		STDMETHODIMP    InsertRow(HCHAPTER hChapter,HACCESSOR hAccessor, void* pData, HROW* phRow);

    private:
        STDMETHODIMP	ApplyAccessorToData( DBCOUNTITEM cBindings, DBBINDING* pBinding,BYTE*  pbProvRow,void* pData,DWORD & dwErrorCount );
		STDMETHODIMP	ValidateArguments(	HROW        hRow,
											HACCESSOR   hAccessor,
											const void  *pData,
											PROWBUFF    *pprowbuff = NULL,
											PACCESSOR *ppkgaccessor = NULL);

		BOOL	CompareData(DBTYPE dwType,void * pData1 , void *pData2);
		HRESULT UpdateDataToRowBuffer(DBCOUNTITEM iBind ,BYTE * pbProvRow,DBBINDING* pBinding,BYTE *pData);
		BOOL	IsNullAccessor(PACCESSOR phAccessor,BYTE * pData );
		HRESULT InsertNewRow(HROW hRow,	HCHAPTER    hChapter,CWbemClassWrapper *& pNewInst);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIColumnsInfo : public IColumnsInfo 		
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CBaseRowObj		*m_pObj;											

	public: 

    	CImpIColumnsInfo(CBaseRowObj *pObj)
		{
	    	DEBUGCODE(m_cRef = 0L);
		    m_pObj		= pObj;
		}

		~CImpIColumnsInfo()												
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));	
           	return m_pObj->GetOuterUnknown()->AddRef();
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
        	return m_pObj->GetOuterUnknown()->Release();

		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

	    STDMETHODIMP	GetColumnInfo(DBORDINAL* pcColumns, DBCOLUMNINFO** prgInfo, OLECHAR** ppStringsBuffer);
		STDMETHODIMP	MapColumnIDs(DBORDINAL, const DBID[], DBORDINAL[]);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIAccessor : public IAccessor 		
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
        CBaseObj    *m_pObj;
		LPEXTBUFFER m_pextbufferAccessor;           // array of accessor ptrs
		LPBITARRAY	m_prowbitsIBuffer;	            // bit array to mark active rows/ or parameters
		BOOL		m_bRowset;

    public: 
        
        CImpIAccessor::CImpIAccessor( CBaseObj *pParentObj,BOOL bRowset = TRUE)
	    {
	        //	Initialize simple member vars
	        DEBUGCODE(m_cRef = 0L);
	        m_pObj			    = pParentObj;
            m_prowbitsIBuffer   = NULL;
        	m_pextbufferAccessor= NULL;
			m_bRowset			= bRowset;
		}

    	~CImpIAccessor()													
		{							
	        //===============================================================
            // Free accessors.
            // Each accessor is allocated via new/delete.
            // We store an array of ptrs to each accessor (m_pextbufferAccessor).
	        //===============================================================
            if (NULL != m_pextbufferAccessor){
                HACCESSOR   hAccessor, hAccessorLast;
                PACCESSOR   pAccessor;

                m_pextbufferAccessor->GetFirstLastItemH( hAccessor, hAccessorLast );
                for (; hAccessor <= hAccessorLast; hAccessor++){

                    m_pextbufferAccessor->GetItemOfExtBuffer( hAccessor, &pAccessor );
                    SAFE_DELETE_PTR( pAccessor );
                }
                DeleteAccessorBuffer();
            }

           	// Delete bit array that marks referenced parameters.
        	DeleteBitArray();
		}

        HRESULT CImpIAccessor::FInit();

        inline CBaseObj* GetBaseObjectPtr() { return m_pObj;}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));		
        	return m_pObj->GetOuterUnknown()->AddRef();
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP	AddRefAccessor(HACCESSOR hAccessor, DBREFCOUNT* pcRefCounts);
	    STDMETHODIMP	CreateAccessor(DBACCESSORFLAGS, DBCOUNTITEM, const DBBINDING[], DBLENGTH, HACCESSOR*, DBBINDSTATUS[]);
		STDMETHODIMP	GetBindings(HACCESSOR, DBACCESSORFLAGS*, DBCOUNTITEM*, DBBINDING**);
		STDMETHODIMP	ReleaseAccessor(HACCESSOR, DBREFCOUNT*);

		// utility member functions
        LPBITARRAY  GetBitArrayPtr()    { return m_prowbitsIBuffer; }
        LPEXTBUFFER GetAccessorPtr()    { return m_pextbufferAccessor;}           // array of accessor ptrs
        BOOL CreateNewBitArray();
        BOOL CreateNewAccessorBuffer();
        void DeleteBitArray()           { SAFE_DELETE_PTR(m_prowbitsIBuffer);}
        void DeleteAccessorBuffer()     { SAFE_DELETE_PTR(m_pextbufferAccessor);}
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIRowsetInfo : public IRowsetInfo 
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

	public: 
		CImpIRowsetInfo( CRowset *pObj )				
		{																	
			DEBUGCODE(m_cRef = 0L);											
			m_pObj		= pObj;												
		}																	
		~CImpIRowsetInfo()													
		{																	
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP			GetReferencedRowset
			(
				DBORDINAL	iOrdinal, 
				REFIID		rrid,
				IUnknown**	ppReferencedRowset
			);

		STDMETHODIMP			GetProperties
		    (
			    const ULONG			cPropertySets,
			    const DBPROPIDSET	rgPropertySets[],
			    ULONG*              pcProperties,
			    DBPROPSET**			prgProperties
		    );

		STDMETHODIMP			GetSpecification(REFIID, IUnknown**);

};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIRowsetIdentity : public IRowsetIdentity 	
{
	private: 
		DEBUGCODE(ULONG m_cRef);										
		CRowset		*m_pObj;											

	public: 
		CImpIRowsetIdentity( CRowset *pObj)		
		{																
			DEBUGCODE(m_cRef = 0L);										
			m_pObj		= pObj;											
		}																
		~CImpIRowsetIdentity()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP	IsSameRow(	HROW hThisRow, 
									HROW hThatRow);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CImpIConvertType : public IConvertType 	
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CBaseObj		*m_pObj;											

	public: 
		CImpIConvertType( CBaseObj *pObj )					
		{																	
			DEBUGCODE(m_cRef = 0L);											
			m_pObj		= pObj;												
		}																	
		~CImpIConvertType()														
		{																	
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP CImpIConvertType::CanConvert
			(
			DBTYPE			wFromType,		//@parm IN | src type
			DBTYPE			wToType,		//@parm IN | dst type
			DBCONVERTFLAGS	dwConvertFlags	//@parm IN | conversion flags
			);
};


class CImpIChapteredRowset : public IChapteredRowset	
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

	public: 
		
		CImpIChapteredRowset( CRowset *pObj )			
		{																
			DEBUGCODE(m_cRef = 0L);										
			m_pObj		= pObj;											
		}																
		~CImpIChapteredRowset()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}
		
		STDMETHODIMP AddRefChapter (HCHAPTER   hChapter, DBREFCOUNT *  pcRefCount);
		STDMETHODIMP ReleaseChapter (HCHAPTER   hChapter,DBREFCOUNT * pcRefCount);

};



class CImpIGetRow : public IGetRow
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

	public: 
		
		CImpIGetRow( CRowset *pObj )			
		{																
			DEBUGCODE(m_cRef = 0L);										
			m_pObj		= pObj;											
		}																
		~CImpIGetRow()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP GetRowFromHROW(IUnknown * pUnkOuter,HROW hRow,REFIID riid,IUnknown ** ppUnk);
		STDMETHODIMP GetURLFromHROW(HROW hRow,LPOLESTR * ppwszURL);
};


class CImplIRowsetRefresh : public IRowsetRefresh
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

		HRESULT CheckIfRowsExists(DBCOUNTITEM cRows,const HROW rghRows[],DBROWSTATUS *   prgRowStatus);
	public: 
		
		CImplIRowsetRefresh( CRowset *pObj )			
		{																
			DEBUGCODE(m_cRef = 0L);
			m_pObj		= pObj;											
		}																
		~CImplIRowsetRefresh()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

		STDMETHODIMP GetLastVisibleData(HROW hRow,HACCESSOR hAccessor,void * pData);

		STDMETHODIMP RefreshVisibleData(HCHAPTER         hChapter,
										DBCOUNTITEM      cRows,
										const HROW       rghRows[],
										BOOL             fOverwrite,
										DBCOUNTITEM *    pcRowsRefreshed,
										HROW **          prghRowsRefreshed,
										DBROWSTATUS **   prgRowStatus);

};


class CImplIParentRowset:public IParentRowset
{
	private: 
		DEBUGCODE(ULONG m_cRef);											
		CRowset		*m_pObj;											

	public: 
		
		CImplIParentRowset( CRowset *pObj )			
		{																
			DEBUGCODE(m_cRef = 0L);
			m_pObj		= pObj;											
		}																
		~CImplIParentRowset()											
		{																
		}

		STDMETHODIMP_(ULONG) AddRef(void)									
		{																
			DEBUGCODE(InterlockedIncrement((long*)&m_cRef));						
			return m_pObj->GetOuterUnknown()->AddRef();								
		}																

		STDMETHODIMP_(ULONG) Release(void)									
		{																
		   DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef);
		   if( lRef < 0 ){
			   ASSERT("Reference count on Object went below 0!")
		   })
		
			return m_pObj->GetOuterUnknown()->Release();								
		}																

		STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)		
		{																	
			return m_pObj->GetOuterUnknown()->QueryInterface(riid, ppv);					
		}

        STDMETHODIMP GetChildRowset( IUnknown __RPC_FAR *pUnkOuter,
										DBORDINAL iOrdinal,
										REFIID riid,
										IUnknown __RPC_FAR *__RPC_FAR *ppRowset);
};

// class for storing instance information for each row in rowset
class CWMIInstance
{
public:
	CWbemClassWrapper *		m_pInstance;
	HROW			m_hRow;
	HSLOT			m_hSlot;
	CWMIInstance *	m_pNext;
	BSTR			m_strKey;
	DBSTATUS		m_dwStatus;

	CWMIInstance()
	{
		m_pInstance = NULL;
		m_hRow		= DBROWSTATUS_S_OK;
		m_pNext		= NULL;
		m_hSlot		= -1;
		m_strKey = Wmioledb_SysAllocString(NULL);
		m_dwStatus	= 0;
	}

	~CWMIInstance()
	{
		if(m_strKey)
		{
			SysFreeString(m_strKey);
		}
	}

	void		SetRowStatus(DBSTATUS dwStatus) { m_dwStatus = dwStatus ; };
	DBSTATUS	GetRowStatus() { return m_dwStatus; };
};

// class to maps HROWS to CWMIInstance
class CWMIInstanceMgr
{
private:
	ULONG m_lCount;					// count of instances in the list;
public:
	CWMIInstance *m_pFirst;

	CWMIInstanceMgr();
	~CWMIInstanceMgr();

	HRESULT				AddInstanceToList(HROW hRow ,CWbemClassWrapper *pInstance ,BSTR strKey, HSLOT hSlot = -1);
	HRESULT				DeleteInstanceFromList(HROW hRow);
	CWbemClassWrapper * GetInstance(HROW hRow);
	HRESULT			  	GetInstanceKey(HROW hRow, BSTR * strKey);

	HRESULT				GetAllHROWs(HROW *&prghRows , DBCOUNTITEM &cRows);
	HRESULT				SetSlot(HROW hRow , HSLOT hSlot);
	HSLOT				GetSlot(HROW hRow);
	BOOL				IsRowExists(HROW hrow);
	BOOL				IsInstanceExist(BSTR strKey);
	BOOL				IsInstanceExist(CWbemClassWrapper *pInstance);
	HROW				GetHRow(BSTR strKey);

	void				SetRowStatus(HROW hRow , DBSTATUS dwStatus);
	DBSTATUS			GetRowStatus(HROW hRow);

};



//=================================================================
//Abstract base class for fetching rows and data for rows
//=================================================================
class CRowFetchObj
{
	void	ClearRowBuffer(void *pData,DBBINDING   *pBinding,int nCurCol);

protected:
	LONG_PTR	GetFirstFetchPos(CRowset *pRowset,DBCOUNTITEM cRows,DBROWOFFSET lOffset);

public:
	virtual HRESULT FetchRows(	CRowset *	 pRowset,
						HCHAPTER		hChapter,        // IN  The Chapter handle.
						DBROWOFFSET		lRowOffset,      // IN  Rows to skip before reading
						DBROWCOUNT		cRows,           // IN  Number of rows to fetch
						DBCOUNTITEM*	pcRowsObtained, // OUT Number of rows obtained
						HROW     **		prghRows) = 0;       // OUT Array of Hrows obtained)

	virtual HRESULT	FetchData(CRowset *	  pRowset,
					  HROW  hRow,             //IN  Row Handle
                      HACCESSOR   hAccessor,  //IN  Accessor to use
                      void       *pData  ) ;

	HRESULT CRowFetchObj::FetchRowsByBookMark(CRowset *	 pRowset,
													HCHAPTER	hChapter,        // IN  The Chapter handle.
													DBROWCOUNT	cRows,           // IN  Number of rows to fetch
													const DBBKMARK rgcbBookmarks[],	//@parm IN  | an array of bookmark sizes
													const BYTE*	rgpBookmarks[],	//@parm IN  | an array of pointers to bookmarks
													HROW		rghRows[],			// OUT Array of Hrows obtained
													DBROWSTATUS rgRowStatus[]);       // OUT status of rows

	HRESULT CRowFetchObj::FetchNextRowsByBookMark(CRowset *	 pRowset,
													HCHAPTER   hChapter,        // IN  The Chapter handle.
													DBBKMARK   cbBookmark,	// size of BOOKMARK
		 											const BYTE *   pBookmark,	// The bookmark from which fetch should start
													DBROWOFFSET    lRowsOffset,
													DBROWCOUNT     cRows,
													DBCOUNTITEM *  pcRowsObtained,
													HROW **        prghRows);
};


//=====================================================================
// Row fetch object for fetching data for rowsets showing instance
//=====================================================================
class CInstanceRowFetchObj : public CRowFetchObj
{
public:
	virtual HRESULT FetchRows(	CRowset *	 pRowset,
						HCHAPTER	hChapter,        // IN  The Chapter handle.
						DBROWOFFSET	lRowOffset,      // IN  Rows to skip before reading
						DBROWCOUNT  cRows,           // IN  Number of rows to fetch
						DBCOUNTITEM*pcRowsObtained, // OUT Number of rows obtained
						HROW       **prghRows);       // OUT Array of Hrows obtained)

};

//=====================================================================
// Row fetch object for fetching data for rowsets qualifiers
//=====================================================================
class CQualifierRowFetchObj : public CRowFetchObj
{
public:
	virtual HRESULT FetchRows(	CRowset *	 pRowset,
						HCHAPTER	hChapter,        // IN  The Chapter handle.
						DBROWOFFSET	lRowOffset,      // IN  Rows to skip before reading
						DBROWCOUNT	cRows,           // IN  Number of rows to fetch
						DBCOUNTITEM*pcRowsObtained, // OUT Number of rows obtained
						HROW     **	prghRows);       // OUT Array of Hrows obtained)

};



inline BOOL CRowset::BitArrayInitialized()     
{ return ((LPBITARRAY)m_pIAccessor->GetBitArrayPtr()) == NULL ? FALSE : TRUE; }

inline LPEXTBUFFER CRowset::GetAccessorBuffer()
{ return (LPEXTBUFFER)m_pIAccessor->GetAccessorPtr(); }


#endif