// MdSync.hxx: Definition of the MdSync class // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_MDSYNC_H__C97912DF_997E_11D0_A5F6_00A0C922E752__INCLUDED_) #define AFX_MDSYNC_H__C97912DF_997E_11D0_A5F6_00A0C922E752__INCLUDED_ #if _MSC_VER >= 1001 #pragma once #endif // _MSC_VER >= 1001 #include "resource.h" // main symbols #include #include #include #include #define TIMEOUT_VALUE 10000 #define THREAD_COUNT 10 #define RANDOM_SEED_SIZE 16 //size of random bits used to generate session key, in bytes #define SEED_MD_DATA_SIZE (RANDOM_SEED_SIZE + SEED_HEADER_SIZE) typedef enum { SCANMODE_QUIT, SCANMODE_SYNC_PROPS, SCANMODE_SYNC_OBJECTS } SCANMODE; class CMdIf { public: CMdIf() { m_pcAdmCom = NULL; m_hmd = NULL; m_fModified = FALSE; } ~CMdIf() { Terminate(); } BOOL Init( LPSTR pszComputer ); BOOL Open( LPWSTR pszOpen = L"", DWORD dwAttr = METADATA_PERMISSION_READ ); BOOL Close(); BOOL Save() { m_pcAdmCom->SaveData(); return TRUE; } BOOL Terminate(); VOID SetModified() { m_fModified = TRUE; } BOOL Enum( LPWSTR pszPath, DWORD i, LPWSTR pName ) { HRESULT hRes; hRes = m_pcAdmCom->EnumKeys( m_hmd, pszPath, pName, i ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL GetAllData( LPWSTR pszPath, LPDWORD pdwRec, LPDWORD pdwDataSet, LPBYTE pBuff, DWORD cBuff, LPDWORD pdwRequired ) { HRESULT hRes; hRes = m_pcAdmCom->GetAllData( m_hmd, pszPath, 0, ALL_METADATA, ALL_METADATA, pdwRec, pdwDataSet, cBuff, pBuff, pdwRequired ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL GetData( LPWSTR pszPath, PMETADATA_RECORD pmd, LPVOID pData, LPDWORD pdwRequired ) { METADATA_RECORD md = *pmd; HRESULT hRes; md.pbMDData = (LPBYTE)pData; hRes = m_pcAdmCom->GetData( m_hmd, pszPath, &md, pdwRequired ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL SetData( LPWSTR pszPath, PMETADATA_RECORD pmd, LPVOID pData ) { METADATA_RECORD md = *pmd; HRESULT hRes; md.pbMDData = (LPBYTE)pData; hRes = m_pcAdmCom->SetData( m_hmd, pszPath, &md ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL DeleteProp( LPWSTR pszPath, PMETADATA_RECORD pmd ) { HRESULT hRes; hRes = m_pcAdmCom->DeleteData( m_hmd, pszPath, pmd->dwMDIdentifier, pmd->dwMDDataType ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL DeleteSubTree( LPWSTR pszPath ) { HRESULT hRes; hRes = m_pcAdmCom->DeleteChildKeys( m_hmd, pszPath ); hRes = m_pcAdmCom->DeleteKey( m_hmd, pszPath ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL AddNode( LPWSTR pszPath ) { HRESULT hRes; hRes = m_pcAdmCom->AddKey( m_hmd, pszPath ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL GetLastChangeTime( LPWSTR pszPath, PFILETIME pftMDLastChangeTime ) { HRESULT hRes; hRes = m_pcAdmCom->GetLastChangeTime( m_hmd, pszPath, pftMDLastChangeTime, FALSE ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL SetLastChangeTime( LPWSTR pszPath, PFILETIME pftMDLastChangeTime ) { HRESULT hRes; hRes = m_pcAdmCom->SetLastChangeTime( m_hmd, pszPath, pftMDLastChangeTime, FALSE ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } private: IMSAdminBaseW * m_pcAdmCom; //interface pointer METADATA_HANDLE m_hmd; BOOL m_fModified; } ; #if defined(ADMEX) class CRpIf { public: CRpIf() { m_pcAdmCom = NULL; } ~CRpIf() { Terminate(); } BOOL Init( LPSTR pszComputer, CLSID* pClsid ); BOOL Terminate(); BOOL GetSignature( BUFFER* pbuf, LPDWORD pdwBufSize ) { DWORD dwRequired; HRESULT hRes; hRes = m_pcAdmCom->GetSignature( pbuf->QuerySize(), (LPBYTE)pbuf->QueryPtr(), &dwRequired ); if ( hRes == RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) ) { if ( !pbuf->Resize( dwRequired ) ) { return FALSE; } hRes = m_pcAdmCom->GetSignature( pbuf->QuerySize(), (LPBYTE)pbuf->QueryPtr(), &dwRequired ); } if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } else { *pdwBufSize = dwRequired; } return TRUE; } BOOL Serialize( BUFFER* pbuf, LPDWORD pdwBufSize ) { DWORD dwRequired; HRESULT hRes; hRes = m_pcAdmCom->Serialize( pbuf->QuerySize(), (LPBYTE)pbuf->QueryPtr(), &dwRequired ); if ( hRes == RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) ) { if ( !pbuf->Resize( dwRequired ) ) { return FALSE; } hRes = m_pcAdmCom->Serialize( pbuf->QuerySize(), (LPBYTE)pbuf->QueryPtr(), &dwRequired ); } if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } else { *pdwBufSize = dwRequired; } return TRUE; } BOOL DeSerialize( BUFFER* pbuf, DWORD cBuff ) { HRESULT hRes; hRes = m_pcAdmCom->DeSerialize( cBuff, (LPBYTE)pbuf->QueryPtr() ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL Propagate( char* pTarget, DWORD cTarget ) { HRESULT hRes; hRes = m_pcAdmCom->Propagate( cTarget, (LPBYTE)pTarget ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } BOOL Propagate2( char* pTarget, DWORD cTarget, DWORD dwF ) { HRESULT hRes; hRes = m_pcAdmCom->Propagate2( cTarget, (LPBYTE)pTarget, dwF ); if ( FAILED( hRes ) ) { SetLastError( HRESULTTOWIN32(hRes) ); return FALSE; } return TRUE; } private: IMSAdminReplication* m_pcAdmCom; //interface pointer } ; #endif class CTargetBitmask { public: CTargetBitmask() { m_pbTargets = NULL; m_dwTargets = 0; } ~CTargetBitmask() { if ( m_pbTargets ) LocalFree( m_pbTargets ); } BOOL Init( DWORD dwNbTargets, BOOL fSt = TRUE ) { if ( m_pbTargets ) { LocalFree( m_pbTargets ); } if ( m_pbTargets = (LPBYTE)LocalAlloc( LMEM_FIXED, dwNbTargets ) ) { memset( m_pbTargets, fSt , dwNbTargets ); m_dwTargets = dwNbTargets; return TRUE; } return FALSE; } DWORD FindUntouchedTarget() { DWORD dwT; for ( dwT = 0 ; dwT < m_dwTargets ; ++dwT ) { if ( m_pbTargets[dwT] ) { m_pbTargets[dwT] = 0x0; return dwT; } } return 0xffffffff; } BOOL GetFlag( DWORD dwI ) { return m_pbTargets[dwI]; } VOID SetFlag( DWORD dwI, DWORD dwV ) { m_pbTargets[dwI] = (BYTE)dwV; } private: LPBYTE m_pbTargets; DWORD m_dwTargets; } ; typedef struct _THREAD_CONTEXT { PVOID pvContext; DWORD dwIndex; HANDLE hSemaphore; } THREAD_CONTEXT, *PTHREAD_CONTEXT; template class CTargetStatus { public: CTargetStatus() { m_pTargets = NULL; m_dwTargets = 0; } ~CTargetStatus() { if ( m_pTargets ) LocalFree( m_pTargets ); } BOOL Init( DWORD dwNbTargets ) { if ( m_pTargets ) { LocalFree( m_pTargets ); } if ( m_pTargets = (T*)LocalAlloc( LMEM_FIXED, dwNbTargets * sizeof(T)) ) { memset( m_pTargets, '\x0' , dwNbTargets * sizeof(T) ); m_dwTargets = dwNbTargets; return TRUE; } return FALSE; } T GetStatus( DWORD dwI ) { return m_pTargets[dwI]; } VOID SetStatus( DWORD dwI, T value ) { m_pTargets[dwI] = value; }; T* GetPtr( DWORD dwI ) { return m_pTargets+dwI; } BOOL IsError() { for ( UINT i = 0 ; i < m_dwTargets ; ++i ) { if ( m_pTargets[i] ) { return TRUE; } } return FALSE; } private: T* m_pTargets; DWORD m_dwTargets; }; class CNodeDesc; #define AER_PHASE1 1 #define AER_PHASE2 2 class CSync { public: CSync(); ~CSync(); VOID Lock() { EnterCriticalSection( &m_csLock ); } VOID Unlock() { LeaveCriticalSection( &m_csLock ); } HRESULT Sync( LPSTR pwszTargets, LPDWORD pdwResults, DWORD dwFlags, SYNC_STAT* pStat ); BOOL GenerateKeySeed(); BOOL PropagateKeySeed(); BOOL DeleteKeySeed(); HRESULT Cancel() { UINT i; m_fCancel = TRUE; if ( m_fInScan ) { for ( i = 0 ; i < m_dwThreads ; ++i ) { SignalWorkItem( i ); } } return S_OK; } BOOL ScanTarget( DWORD dwTarget ); VOID SignalWorkItem( DWORD dwI ) { ReleaseSemaphore( m_ThreadContext.GetPtr(dwI)->hSemaphore, 1, NULL ); } VOID WaitForWorkItem( DWORD dwI ) { WaitForSingleObject( m_ThreadContext.GetPtr(dwI)->hSemaphore, INFINITE ); } DWORD GetTargetCount() { return m_dwTargets; } VOID SetTargetError( DWORD dwTarget, DWORD dwError ); DWORD GetTargetError(DWORD dwTarget ) { return m_TargetStatus.GetStatus( dwTarget ); } BOOL IsLocal( DWORD dwTarget ) { return !m_bmIsRemote.GetFlag( dwTarget ); } BOOL IsCancelled() { return m_fCancel; } BOOL GetProp( LPWSTR pszPath, DWORD dwPropId, DWORD dwUserType, DWORD dwDataType, LPBYTE* ppBuf, LPDWORD pdwLen ); VOID IncrementSourceScan() { ++m_pStat->m_dwSourceScan; } VOID IncrementTargetScan( DWORD dwTarget ) { ++m_pStat->m_adwTargets[dwTarget*2]; } VOID IncrementTargetTouched( DWORD dwTarget ) { ++m_pStat->m_adwTargets[dwTarget*2+1]; } VOID SetSourceComplete() { m_pStat->m_fSourceComplete = TRUE; } DWORD QueryFlags() { return m_dwFlags;} CMdIf* GetSourceIf() { return &m_Source; } CMdIf* GetTargetIf( DWORD i ) { return m_pTargets[i]; } BOOL ScanThread(); BOOL ProcessQueuedRequest(); BOOL ProcessAdminExReplication( LPWSTR, LPSTR, DWORD ); BOOL QueueRequest( DWORD dwId, LPWSTR pszPath, DWORD dwTarget, FILETIME* ); VOID SetModified( DWORD i ) { m_pTargets[i]->SetModified(); } VOID SetTargetSignatureMismatch( DWORD i, DWORD iC, BOOL fSt) { m_bmTargetSignatureMismatch.SetFlag( i + iC*m_dwTargets, fSt ); } DWORD GetTargetSignatureMismatch( DWORD i, DWORD iC ) { return (DWORD)m_bmTargetSignatureMismatch.GetFlag(i + iC*m_dwTargets); } LIST_ENTRY m_QueuedRequestsHead; LONG m_lThreads; private: CNodeDesc* m_pRoot; CMdIf** m_pTargets; DWORD m_dwTargets; CMdIf m_Source; CTargetStatus m_TargetStatus; CTargetStatus m_ThreadHandle; CTargetStatus m_ThreadContext; BOOL m_fCancel; DWORD m_dwThreads; CTargetBitmask m_bmIsRemote; CTargetBitmask m_bmTargetSignatureMismatch; CRITICAL_SECTION m_csQueuedRequestsList; CRITICAL_SECTION m_csLock; BOOL m_fInScan; DWORD m_dwFlags; SYNC_STAT* m_pStat; BYTE m_rgbSeed[SEED_MD_DATA_SIZE]; DWORD m_cbSeed; } ; class CNseRequest { public: CNseRequest::CNseRequest(); CNseRequest::~CNseRequest(); BOOL Match( LPWSTR pszPath, DWORD dwId ) { return !_wcsicmp( pszPath, m_pszPath ) && dwId == m_dwId; } BOOL Init( LPWSTR pszPath, LPWSTR pszCreatePath, LPWSTR pszCreateObject, DWORD dwId, DWORD dwTargetCount, LPWSTR pszModifPath, FILETIME*, METADATA_RECORD* ); VOID AddTarget( DWORD i ) { m_bmTarget.SetFlag( i, TRUE ); } BOOL Process( CSync* ); LIST_ENTRY m_QueuedRequestsList; private: LPWSTR m_pszPath; LPWSTR m_pszCreatePath; LPWSTR m_pszCreateObject; LPWSTR m_pszModifPath; DWORD m_dwId; DWORD m_dwTargetCount; CTargetBitmask m_bmTarget; LPBYTE m_pbData; DWORD m_dwData; FILETIME m_ftModif; METADATA_RECORD m_md; } ; class CProps { public: CProps(); ~CProps(); BOOL GetAll( CMdIf*, LPWSTR ); VOID SetRefCount( DWORD dwRefCount ) { m_lRefCount = (LONG)dwRefCount; } VOID Dereference() { if ( !InterlockedDecrement( &m_lRefCount ) ) { if ( m_Props ) { LocalFree( m_Props ); m_Props = NULL; } } } BOOL IsNse( DWORD dwId ) { return dwId == MD_SERIAL_CERT11 || dwId == MD_SERIAL_DIGEST; } BOOL NseIsDifferent( DWORD dwId, LPBYTE pSourceData, DWORD dwSourceLen, LPBYTE pTargetData, DWORD dwTargetLen, LPWSTR pszPath, DWORD dwTarget ); BOOL NseSet( DWORD dwId, CSync*, LPWSTR pszPath, DWORD dwTarget ); LPBYTE GetProps() { return m_Props; } DWORD GetPropsCount() { return m_dwProps; } private: LPBYTE m_Props; DWORD m_dwProps; DWORD m_dwLenProps; LONG m_lRefCount; } ; class CNodeDesc { public: CNodeDesc( CSync* ); ~CNodeDesc(); BOOL Scan( CSync* pSync ); BOOL ScanTarget( DWORD dwTarget ); BOOL SetPath( LPWSTR pszPath ) { if ( m_pszPath ) { LocalFree( m_pszPath ); } if ( !(m_pszPath = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszPath)+1)*sizeof(WCHAR) )) ) { return FALSE; } wcscpy( m_pszPath, pszPath ); return TRUE; } LPWSTR GetPath() { return m_pszPath; } BOOL DoWork( SCANMODE sm, DWORD dwtarget ); BOOL BuildChildObjectsList( CMdIf*, LPWSTR pszPath ); // list of child CNodeDesc LIST_ENTRY m_ChildHead; // to CNodeDesc LIST_ENTRY m_ChildList; private: // source properties CProps m_Props; CTargetBitmask m_bmProps; CTargetBitmask m_bmObjs; BOOL m_fHasProps; BOOL m_fHasObjs; // LPWSTR m_pszPath; CSync* m_pSync; } ; ///////////////////////////////////////////////////////////////////////////// // MdSync class MdSync : public IMdSync, public CComObjectRoot, public CComCoClass { public: MdSync() {} BEGIN_COM_MAP(MdSync) COM_INTERFACE_ENTRY(IMdSync) END_COM_MAP() //DECLARE_NOT_AGGREGATABLE(MdSync) // Remove the comment from the line above if you don't want your object to // support aggregation. DECLARE_REGISTRY_RESOURCEID(IDR_MdSync) // IMdSync public: STDMETHOD(Synchronize)( LPSTR mszTargets, LPDWORD pdwResults, DWORD dwFlags, LPDWORD pdwStat ); STDMETHOD(Cancel) (); private: CSync m_Sync; }; #endif // !defined(AFX_MDSYNC_H__C97912DF_997E_11D0_A5F6_00A0C922E752__INCLUDED_)