Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2966 lines
71 KiB

  1. // MdSync.cpp : Implementation of CSyncApp and DLL registration.
  2. extern "C" {
  3. #include "nt.h"
  4. #include "ntrtl.h"
  5. #include "nturtl.h"
  6. #include "windows.h"
  7. #include "stdio.h"
  8. #include "stdlib.h"
  9. } // extern "C"
  10. #include <limits.h>
  11. #include <ole2.h>
  12. #include <wincrypt.h>
  13. #include <dbgutil.h>
  14. #include <buffer.hxx>
  15. #include "mdsync.h"
  16. #include "stdafx.h"
  17. #include <iadmext.h>
  18. #define ADMEX
  19. #if defined(ADMEX)
  20. #undef DEFINE_GUID
  21. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  22. EXTERN_C const GUID name \
  23. = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  24. #include <admex.h>
  25. #undef DEFINE_GUID
  26. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  27. EXTERN_C const GUID FAR name
  28. #endif
  29. #include "mdsync.hxx"
  30. //
  31. #include "comrepl_i.c"
  32. #include "comrepl.h"
  33. //
  34. // Global Functions
  35. //
  36. HRESULT
  37. MTS_Propagate2
  38. (
  39. /* [in] */ DWORD dwBufferSize,
  40. /* [size_is][in] */ unsigned char __RPC_FAR *pszBuffer,
  41. /* [in] */ DWORD dwSignatureMismatch
  42. );
  43. //
  44. // Globals
  45. //
  46. DWORD g_dwFalse = FALSE;
  47. const INT COMPUTER_CHARACTER_SIZE = 64;
  48. /////////////////////////////////////////////////////////////////////////////
  49. //
  50. CProps::CProps(
  51. )
  52. /*++
  53. Routine Description:
  54. Property list constructor
  55. Arguments:
  56. None
  57. Returns:
  58. Nothing
  59. --*/
  60. {
  61. m_Props = NULL;
  62. m_dwProps = m_dwLenProps = 0;
  63. m_lRefCount = 0;
  64. }
  65. CProps::~CProps(
  66. )
  67. /*++
  68. Routine Description:
  69. Property list destructor
  70. Arguments:
  71. None
  72. Returns:
  73. Nothing
  74. --*/
  75. {
  76. if ( m_Props )
  77. {
  78. LocalFree( m_Props );
  79. }
  80. }
  81. CNodeDesc::CNodeDesc(
  82. CSync* pSync
  83. )
  84. /*++
  85. Routine Description:
  86. Metabase node descriptor constructor
  87. Arguments:
  88. pSync - ptr to synchronizer object
  89. Returns:
  90. Nothing
  91. --*/
  92. {
  93. InitializeListHead(&m_ChildHead);
  94. m_pszPath = NULL;
  95. m_pSync = pSync;
  96. m_fHasProps = FALSE;
  97. m_fHasObjs = FALSE;
  98. }
  99. CNodeDesc::~CNodeDesc(
  100. )
  101. /*++
  102. Routine Description:
  103. Metabase node descriptor destructor
  104. Arguments:
  105. None
  106. Returns:
  107. Nothing
  108. --*/
  109. {
  110. LIST_ENTRY* pChild;
  111. CNodeDesc* pNode;
  112. if ( m_pszPath )
  113. {
  114. LocalFree( m_pszPath );
  115. }
  116. while ( !IsListEmpty( &m_ChildHead ))
  117. {
  118. pNode = CONTAINING_RECORD( m_ChildHead.Flink,
  119. CNodeDesc,
  120. m_ChildList );
  121. RemoveEntryList( &pNode->m_ChildList );
  122. delete pNode;
  123. }
  124. }
  125. BOOL
  126. CNodeDesc::BuildChildObjectsList(
  127. CMdIf* pMd,
  128. LPWSTR pszPath
  129. )
  130. /*++
  131. Routine Description:
  132. Build list of child object of this node
  133. Arguments:
  134. pMd - metabase admin interface
  135. pszPath - path of current node
  136. Returns:
  137. Nothing
  138. --*/
  139. {
  140. CNodeDesc* pChild;
  141. WCHAR achPath[METADATA_MAX_NAME_LEN*2];
  142. WCHAR achSrcPath[METADATA_MAX_NAME_LEN];
  143. DWORD dwP = wcslen( pszPath );
  144. UINT i;
  145. DWORD dwRequired;
  146. //
  147. // Ugly path trick : metabase will remove trailing '/',
  148. // so to specify an empty directory at the end of path
  149. // must add an additional trailing '/'
  150. //
  151. memcpy( achSrcPath, pszPath, (dwP + 1) * sizeof(WCHAR) );
  152. if ( dwP && pszPath[dwP-1] == L'/' )
  153. {
  154. achSrcPath[dwP] = L'/';
  155. achSrcPath[dwP+1] = L'\0';
  156. }
  157. memcpy( achPath, pszPath, dwP * sizeof(WCHAR) );
  158. achPath[dwP++] = L'/';
  159. //
  160. // enumerate child
  161. //
  162. for ( i = 0 ; ; ++i )
  163. {
  164. if ( pMd->Enum( achSrcPath, i, achPath+dwP ) )
  165. {
  166. if ( pChild = new CNodeDesc( m_pSync ) )
  167. {
  168. pChild->SetPath( achPath );
  169. InsertHeadList( &m_ChildHead, &pChild->m_ChildList );
  170. }
  171. else
  172. {
  173. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  174. return FALSE;
  175. }
  176. }
  177. else if ( GetLastError() != ERROR_NO_MORE_ITEMS )
  178. {
  179. return FALSE;
  180. }
  181. else
  182. {
  183. break;
  184. }
  185. }
  186. return TRUE;
  187. }
  188. BOOL
  189. CProps::GetAll(
  190. CMdIf* pMd,
  191. LPWSTR pszPath
  192. )
  193. /*++
  194. Routine Description:
  195. Get all properties for this node
  196. Arguments:
  197. pMd - metabase admin interface
  198. pszPath - path of current node
  199. Returns:
  200. Nothing
  201. --*/
  202. {
  203. DWORD dwRec;
  204. DWORD dwDataSet;
  205. BYTE abBuff[4096];
  206. DWORD dwRequired;
  207. if ( pMd->GetAllData( pszPath, &dwRec, &dwDataSet, abBuff, sizeof(abBuff), &dwRequired ) )
  208. {
  209. //
  210. // MetaBase does not update dwRequired supplied buffer is big enough
  211. // we must assume the whole buffer was used.
  212. //
  213. dwRequired = sizeof(abBuff);
  214. m_Props = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired );
  215. if ( !m_Props )
  216. {
  217. return FALSE;
  218. }
  219. m_dwProps = dwRec;
  220. m_dwLenProps = dwRequired;
  221. memcpy( m_Props, abBuff, dwRequired );
  222. return TRUE;
  223. }
  224. else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  225. {
  226. m_Props = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired );
  227. if ( !m_Props )
  228. {
  229. return FALSE;
  230. }
  231. if ( pMd->GetAllData( pszPath, &dwRec, &dwDataSet, m_Props, dwRequired, &dwRequired ) )
  232. {
  233. m_dwLenProps = dwRequired;
  234. m_dwProps = dwRec;
  235. return TRUE;
  236. }
  237. LocalFree( m_Props );
  238. m_Props = NULL;
  239. }
  240. return FALSE;
  241. }
  242. BOOL
  243. CSync::GetProp(
  244. LPWSTR pszPath,
  245. DWORD dwPropId,
  246. DWORD dwUserType,
  247. DWORD dwDataType,
  248. LPBYTE* ppBuf,
  249. LPDWORD pdwLen
  250. )
  251. /*++
  252. Routine Description:
  253. Get property for path
  254. Arguments:
  255. pszPath - path of current node
  256. dwPropId - metadata property ID
  257. dwUserType - metadata user type
  258. dwDataType - metadata data type
  259. ppBuf - update with ptr to LocalAlloc'ed buffer or NULL if error
  260. pdwLen - updated with length
  261. Returns:
  262. Nothing
  263. --*/
  264. {
  265. DWORD dwRec;
  266. DWORD dwDataSet;
  267. DWORD dwRequired;
  268. METADATA_RECORD md;
  269. memset( &md, '\0', sizeof(md) );
  270. md.dwMDDataType = dwDataType;
  271. md.dwMDUserType = dwUserType;
  272. md.dwMDIdentifier = dwPropId;
  273. md.dwMDDataLen = 0;
  274. if ( !wcsncmp( pszPath, L"LM/", 3 ) )
  275. {
  276. pszPath += 3;
  277. }
  278. if ( !m_Source.GetData( pszPath, &md, NULL, &dwRequired ) &&
  279. GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  280. {
  281. *ppBuf = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired );
  282. if ( !*ppBuf )
  283. {
  284. return FALSE;
  285. }
  286. *pdwLen = md.dwMDDataLen = dwRequired;
  287. if ( m_Source.GetData( pszPath, &md, *ppBuf, &dwRequired ) )
  288. {
  289. return TRUE;
  290. }
  291. LocalFree( *ppBuf );
  292. }
  293. *ppBuf = NULL;
  294. return FALSE;
  295. }
  296. CSync::CSync(
  297. )
  298. /*++
  299. Routine Description:
  300. Synchronizer constructor
  301. Arguments:
  302. None
  303. Returns:
  304. Nothing
  305. --*/
  306. {
  307. m_pRoot = NULL;
  308. m_pTargets = NULL;
  309. m_dwTargets = 0;
  310. m_fCancel = FALSE;
  311. InitializeListHead( &m_QueuedRequestsHead );
  312. INITIALIZE_CRITICAL_SECTION( &m_csQueuedRequestsList );
  313. INITIALIZE_CRITICAL_SECTION( &m_csLock );
  314. m_fInScan = FALSE;
  315. m_cbSeed = SEED_MD_DATA_SIZE;
  316. memset( m_rgbSeed, 0, m_cbSeed );
  317. }
  318. CSync::~CSync(
  319. )
  320. /*++
  321. Routine Description:
  322. Synchronizer destructor
  323. Arguments:
  324. None
  325. Returns:
  326. Nothing
  327. --*/
  328. {
  329. UINT i;
  330. if ( m_pTargets )
  331. {
  332. for ( i = 0 ; i < m_dwTargets ; ++i )
  333. {
  334. if ( m_pTargets[i] )
  335. {
  336. delete m_pTargets[i];
  337. }
  338. }
  339. LocalFree( m_pTargets );
  340. }
  341. LIST_ENTRY* pChild;
  342. CNseRequest* pReq;
  343. while ( !IsListEmpty( &m_QueuedRequestsHead ))
  344. {
  345. pReq = CONTAINING_RECORD( m_QueuedRequestsHead.Flink,
  346. CNseRequest,
  347. m_QueuedRequestsList );
  348. RemoveEntryList( &pReq->m_QueuedRequestsList );
  349. delete pReq;
  350. }
  351. DeleteCriticalSection( &m_csQueuedRequestsList );
  352. DeleteCriticalSection( &m_csLock );
  353. }
  354. VOID
  355. CSync::SetTargetError(
  356. DWORD dwTarget,
  357. DWORD dwError
  358. )
  359. /*++
  360. Routine Description:
  361. Set error status for specified target
  362. Arguments:
  363. dwTarget - target ID
  364. dwError - error code
  365. Returns:
  366. Nothing
  367. --*/
  368. {
  369. m_TargetStatus.SetStatus( dwTarget, dwError );
  370. }
  371. DWORD
  372. WINAPI
  373. ScanThread(
  374. LPVOID pV
  375. )
  376. /*++
  377. Routine Description:
  378. thread scanning a target for synchronization
  379. Arguments:
  380. pV - ptr to scan context
  381. Returns:
  382. Error code, 0 if success
  383. --*/
  384. {
  385. HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  386. if (FAILED(hr))
  387. {
  388. return HRESULTTOWIN32(hr);
  389. }
  390. THREAD_CONTEXT * pThreadContext = (THREAD_CONTEXT *)pV;
  391. CSync * pSync = (CSync *) pThreadContext->pvContext;
  392. if ( !( pSync->ScanTarget( pThreadContext->dwIndex)))
  393. {
  394. CoUninitialize();
  395. return GetLastError();
  396. }
  397. CoUninitialize();
  398. return 0;
  399. }
  400. BOOL
  401. CSync::ScanTarget(
  402. DWORD dwI
  403. )
  404. /*++
  405. Routine Description:
  406. Scan target for synchronization
  407. Arguments:
  408. dwI - target ID
  409. Returns:
  410. TRUE if success, otherwise FALSE
  411. --*/
  412. {
  413. BOOL fSt;
  414. fSt = m_pRoot->ScanTarget( dwI );
  415. InterlockedDecrement( &m_lThreads );
  416. return fSt;
  417. }
  418. BOOL
  419. CSync::GenerateKeySeed( )
  420. /*++
  421. Routine Description:
  422. Generate the seed which will be used to derive the session key for encryption and
  423. write it to the metabase
  424. Arguments:
  425. Returns:
  426. TRUE if successful, FALSE if not
  427. --*/
  428. {
  429. #ifdef NO_ENCRYPTION
  430. return TRUE;
  431. #else
  432. HCRYPTPROV hProv = NULL;
  433. BOOL fOk = TRUE;
  434. ALG_ID aiAlg = CALG_MD5;
  435. DWORD i = 0;
  436. if ( !m_Source.Open( L"/LM/W3SVC", METADATA_PERMISSION_WRITE ) )
  437. {
  438. return FALSE;
  439. }
  440. //
  441. // Seed header with version information, hash algorithm used and size of
  442. // seed used to generate the session key
  443. //
  444. m_rgbSeed[i++] = IIS_SEED_MAJOR_VERSION;
  445. m_rgbSeed[i++] = IIS_SEED_MINOR_VERSION;
  446. memcpy( m_rgbSeed + i, &aiAlg, sizeof( ALG_ID ) );
  447. i += sizeof( ALG_ID );
  448. m_rgbSeed[i++] = RANDOM_SEED_SIZE;
  449. DBG_ASSERT( i == SEED_HEADER_SIZE );
  450. //
  451. // Generate the seed
  452. //
  453. if ( ( fOk = CryptAcquireContext( &hProv,
  454. NULL,
  455. NULL,
  456. PROV_RSA_FULL,
  457. CRYPT_VERIFYCONTEXT ) ) &&
  458. ( fOk = CryptGenRandom( hProv,
  459. RANDOM_SEED_SIZE,
  460. m_rgbSeed + SEED_HEADER_SIZE ) ) )
  461. {
  462. //
  463. // Write the seed to the metabase
  464. //
  465. METADATA_RECORD mdr;
  466. MD_SET_DATA_RECORD( &mdr,
  467. MD_SSL_REPLICATION_INFO,
  468. METADATA_SECURE,
  469. IIS_MD_UT_SERVER,
  470. BINARY_METADATA,
  471. m_cbSeed,
  472. m_rgbSeed );
  473. fOk = m_Source.SetData( MB_REPLICATION_PATH,
  474. &mdr,
  475. (LPVOID) m_rgbSeed );
  476. }
  477. if ( hProv )
  478. {
  479. CryptReleaseContext( hProv,
  480. 0 );
  481. }
  482. m_Source.Close();
  483. return fOk;
  484. #endif // NO_ENCRYPTION
  485. }
  486. BOOL CSync::PropagateKeySeed( VOID )
  487. /*++
  488. Routine Description:
  489. Propagate the session key seed to all the remote machines
  490. Arguments:
  491. None
  492. Returns:
  493. TRUE if successful, FALSE if not
  494. --*/
  495. {
  496. #ifdef NO_ENCRYPTION
  497. return TRUE;
  498. #else
  499. HRESULT hRes = S_OK;
  500. for ( DWORD dwIndex = 0; dwIndex < m_dwTargets; dwIndex++ )
  501. {
  502. if ( m_bmIsRemote.GetFlag( dwIndex ))
  503. {
  504. if ( !m_pTargets[dwIndex]->Open( L"/LM/W3SVC",
  505. METADATA_PERMISSION_WRITE ) )
  506. {
  507. if ( GetLastError() == ERROR_SUCCESS )
  508. {
  509. SetLastError( RPC_S_SERVER_UNAVAILABLE );
  510. }
  511. m_TargetStatus.SetStatus( dwIndex, GetLastError() );
  512. }
  513. else
  514. {
  515. //
  516. // Write the seed to the remote metabase
  517. //
  518. METADATA_RECORD mdr;
  519. MD_SET_DATA_RECORD( &mdr,
  520. MD_SSL_REPLICATION_INFO,
  521. METADATA_SECURE,
  522. IIS_MD_UT_SERVER,
  523. BINARY_METADATA,
  524. m_cbSeed,
  525. m_rgbSeed );
  526. if ( !m_pTargets[dwIndex]->SetData( MB_REPLICATION_PATH,
  527. &mdr,
  528. (LPVOID) m_rgbSeed ) )
  529. {
  530. m_TargetStatus.SetStatus( dwIndex, GetLastError() );
  531. }
  532. m_pTargets[dwIndex]->Close() ;
  533. }
  534. } // if ( m_bmIsRemote
  535. } // for ( DWORD dwIndex
  536. return TRUE;
  537. #endif //NO_ENCRYPTION
  538. } //::PropagateKeySeed
  539. BOOL CSync::DeleteKeySeed( VOID )
  540. /*++
  541. Routine Description:
  542. Deletes the session key seed from the MB
  543. Arguments:
  544. None
  545. Returns:
  546. TRUE if successful, FALSE if not
  547. --*/
  548. {
  549. #ifdef NO_ENCRYPTION
  550. return TRUE;
  551. #else
  552. BOOL fOk = TRUE;
  553. if ( !m_Source.Open( L"/LM/W3SVC", METADATA_PERMISSION_WRITE ) )
  554. {
  555. return FALSE;
  556. }
  557. METADATA_RECORD mdr;
  558. MD_SET_DATA_RECORD( &mdr,
  559. MD_SSL_REPLICATION_INFO,
  560. METADATA_SECURE,
  561. IIS_MD_UT_SERVER,
  562. BINARY_METADATA,
  563. 0,
  564. NULL );
  565. fOk = m_Source.DeleteProp( MB_REPLICATION_PATH,
  566. &mdr );
  567. m_Source.Close();
  568. return fOk;
  569. #endif //NO_ENCRYPTION
  570. }
  571. HRESULT
  572. CSync::Sync(
  573. LPSTR pszTargets,
  574. LPDWORD pdwResults,
  575. DWORD dwFlags,
  576. SYNC_STAT* pStat
  577. )
  578. /*++
  579. Routine Description:
  580. Synchronize targets with source
  581. Arguments:
  582. pszTargets - multisz of target computer names
  583. can include local computer, will be ignored during synchro
  584. pdwResults - updated with error code for each target
  585. dwFlags - flags, no flag defined for now. Should be 0.
  586. pStat - ptr to stat struct
  587. Returns:
  588. TRUE if success, otherwise FALSE
  589. --*/
  590. {
  591. LPSTR p;
  592. HRESULT hRes = S_OK;
  593. CHAR achLocalComputer[MAX_COMPUTERNAME_LENGTH+1];
  594. BOOL fIsError;
  595. DWORD dwSize;
  596. UINT i;
  597. LPWSTR pClsidList;
  598. BOOL fGotSeed = FALSE;
  599. m_fInScan = FALSE;
  600. if ( m_pRoot )
  601. {
  602. return RETURNCODETOHRESULT(ERROR_IO_PENDING);
  603. }
  604. if ( !(m_pRoot = new CNodeDesc( this )) )
  605. {
  606. return RETURNCODETOHRESULT( ERROR_NOT_ENOUGH_MEMORY );
  607. }
  608. //
  609. // Init MetaData COM I/F on local system
  610. //
  611. m_dwThreads = 0;
  612. dwSize = sizeof(achLocalComputer);
  613. if ( !m_Source.Init( NULL ) ||
  614. !GetComputerName( achLocalComputer, &dwSize ) )
  615. {
  616. hRes = RETURNCODETOHRESULT( GetLastError() );
  617. goto Exit;
  618. }
  619. //
  620. // Generate seed for session key used during replication
  621. //
  622. if ( !GenerateKeySeed() )
  623. {
  624. DBGPRINTF((DBG_CONTEXT,
  625. "GenerateKeySeed() failed : 0x%x\n",
  626. GetLastError() ));
  627. hRes = RETURNCODETOHRESULT( GetLastError() );
  628. goto Exit;
  629. }
  630. else
  631. {
  632. fGotSeed = TRUE;
  633. }
  634. //
  635. // For the rest of the replication, we need an open read handle to the metabase; we open
  636. // the read handle -after- we've generated and written the seed for the session key to the
  637. // metabase so as not to cause lock
  638. //
  639. if ( !m_Source.Open( L"/LM/", METADATA_PERMISSION_READ ) )
  640. {
  641. hRes = RETURNCODETOHRESULT( GetLastError() );
  642. goto Exit;
  643. }
  644. //
  645. // Get CLSIDs of extensions
  646. //
  647. if ( !GetProp( IISADMIN_EXTENSIONS_CLSID_MD_KEYW,
  648. IISADMIN_EXTENSIONS_CLSID_MD_ID,
  649. IIS_MD_UT_SERVER,
  650. MULTISZ_METADATA,
  651. (LPBYTE*)&pClsidList,
  652. &dwSize ) )
  653. {
  654. pClsidList = NULL;
  655. }
  656. //
  657. // Allocate ptr to target systems
  658. //
  659. for ( m_dwTargets = 0, p = pszTargets ; *p ; p += strlen(p)+1, ++m_dwTargets )
  660. {
  661. }
  662. if ( !(m_pTargets = (CMdIf**)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED,
  663. sizeof(CMdIf*)*m_dwTargets)) )
  664. {
  665. hRes = RETURNCODETOHRESULT( ERROR_NOT_ENOUGH_MEMORY );
  666. goto Exit;
  667. }
  668. if ( !m_TargetStatus.Init( m_dwTargets ) ||
  669. !m_bmIsRemote.Init( m_dwTargets ) ||
  670. !m_ThreadHandle.Init( m_dwTargets ) ||
  671. !m_ThreadContext.Init( m_dwTargets ) )
  672. {
  673. hRes = RETURNCODETOHRESULT( GetLastError() );
  674. goto Exit;
  675. }
  676. //
  677. // Init MetaData COM I/F to targets system
  678. //
  679. for ( i = 0, p = pszTargets ; *p ; p += strlen(p)+1, ++i )
  680. {
  681. if ( !(m_pTargets[i] = new CMdIf()) )
  682. {
  683. hRes = RETURNCODETOHRESULT( ERROR_NOT_ENOUGH_MEMORY );
  684. goto Exit;
  685. }
  686. //
  687. // set flag indicating whether it's a remote machine
  688. //
  689. if ( !_stricmp( p, achLocalComputer ) )
  690. {
  691. m_bmIsRemote.SetFlag( i, FALSE );
  692. }
  693. //
  694. // if it's a remote machine, actually get an interface pointer
  695. //
  696. if ( m_bmIsRemote.GetFlag( i ) )
  697. {
  698. if ( !m_pTargets[i]->Init( p ) )
  699. {
  700. if ( GetLastError() == ERROR_SUCCESS )
  701. {
  702. SetLastError( RPC_S_SERVER_UNAVAILABLE );
  703. }
  704. m_TargetStatus.SetStatus( i, GetLastError() );
  705. }
  706. }
  707. }
  708. m_dwFlags = dwFlags;
  709. //
  710. // Copy session key seed to remote machines
  711. //
  712. PropagateKeySeed();
  713. //
  714. // Process replication extensions ( phase 1 )
  715. //
  716. if ( pClsidList )
  717. {
  718. if ( !ProcessAdminExReplication( pClsidList, pszTargets, AER_PHASE1 ) )
  719. {
  720. hRes = RETURNCODETOHRESULT( GetLastError() );
  721. }
  722. }
  723. //
  724. // Open MetaData on targets system
  725. //
  726. for ( i = 0, p = pszTargets ; *p ; p += strlen(p)+1, ++i )
  727. {
  728. if ( m_bmIsRemote.GetFlag( i ) )
  729. {
  730. if ( !m_pTargets[i]->Open( L"/LM/",
  731. METADATA_PERMISSION_READ |
  732. METADATA_PERMISSION_WRITE ) )
  733. {
  734. if ( GetLastError() == ERROR_SUCCESS )
  735. {
  736. SetLastError( RPC_S_SERVER_UNAVAILABLE );
  737. }
  738. m_TargetStatus.SetStatus( i, GetLastError() );
  739. }
  740. }
  741. }
  742. //
  743. // Create thread pool
  744. //
  745. m_lThreads = 0;
  746. for ( i = 0 ; i < m_dwTargets ; ++i )
  747. {
  748. THREAD_CONTEXT threadContext;
  749. DWORD dwId;
  750. HANDLE hSem;
  751. #if IIS_NAMED_WIN32_OBJECTS
  752. CHAR objName[sizeof("CSync::m_ThreadContext( 1234567890*3+2 )")];
  753. #else
  754. LPSTR objName = NULL;
  755. #endif
  756. threadContext.pvContext = this;
  757. threadContext.dwIndex = i;
  758. #if IIS_NAMED_WIN32_OBJECTS
  759. wsprintfA(
  760. objName,
  761. "CSync::m_ThreadContext( %u*3+2 )",
  762. i
  763. );
  764. #endif
  765. hSem = IIS_CREATE_SEMAPHORE(
  766. objName,
  767. this,
  768. 0,
  769. INT_MAX
  770. );
  771. threadContext.hSemaphore = hSem;
  772. m_ThreadContext.SetStatus( i, threadContext );
  773. if ( NULL == hSem )
  774. {
  775. hRes = RETURNCODETOHRESULT( GetLastError() );
  776. break;
  777. }
  778. m_ThreadHandle.SetStatus( i,
  779. CreateThread( NULL,
  780. 0,
  781. (LPTHREAD_START_ROUTINE)::ScanThread,
  782. m_ThreadContext.GetPtr( i ),
  783. 0,
  784. &dwId )
  785. );
  786. if ( m_ThreadHandle.GetStatus( i ) )
  787. {
  788. InterlockedIncrement( &m_lThreads );
  789. ++m_dwThreads;
  790. }
  791. else
  792. {
  793. CloseHandle( m_ThreadContext.GetPtr( i )->hSemaphore );
  794. hRes = RETURNCODETOHRESULT( GetLastError() );
  795. break;
  796. }
  797. }
  798. m_fInScan = TRUE;
  799. //
  800. // Launch scan
  801. //
  802. m_pStat = pStat;
  803. m_pStat->m_dwSourceScan = 0;
  804. m_pStat->m_fSourceComplete = FALSE;
  805. memset( m_pStat->m_adwTargets, '\0', sizeof(DWORD)*2*m_dwTargets );
  806. if ( hRes == S_OK )
  807. {
  808. if ( !m_pRoot->SetPath( L"" ) ||
  809. !m_pRoot->Scan( this ) )
  810. {
  811. hRes = RETURNCODETOHRESULT( GetLastError() );
  812. Cancel();
  813. }
  814. else
  815. {
  816. SetSourceComplete();
  817. }
  818. }
  819. else
  820. {
  821. Cancel();
  822. }
  823. //
  824. // wait for all threads to exit
  825. //
  826. for ( ;; )
  827. {
  828. if ( m_lThreads == 0 )
  829. {
  830. break;
  831. }
  832. Sleep( 1000 );
  833. }
  834. //
  835. // Wait for all threads to be terminated
  836. //
  837. WaitForMultipleObjects( m_dwThreads, m_ThreadHandle.GetPtr(0), TRUE, 5000 );
  838. m_fInScan = FALSE;
  839. for ( i = 0 ; i < m_dwThreads ; ++i )
  840. {
  841. DWORD dwS;
  842. if ( !GetExitCodeThread( m_ThreadHandle.GetStatus(i), &dwS ) )
  843. {
  844. dwS = GetLastError();
  845. }
  846. if ( hRes == S_OK && dwS )
  847. {
  848. hRes = RETURNCODETOHRESULT( dwS );
  849. }
  850. CloseHandle( m_ThreadHandle.GetStatus(i) );
  851. CloseHandle( m_ThreadContext.GetPtr(i)->hSemaphore );
  852. }
  853. //
  854. // Process replication extensions ( phase 2 )
  855. //
  856. if ( pClsidList )
  857. {
  858. if ( !ProcessAdminExReplication( pClsidList, pszTargets, AER_PHASE2 ) )
  859. {
  860. hRes = RETURNCODETOHRESULT( GetLastError() );
  861. }
  862. LocalFree( pClsidList );
  863. }
  864. //
  865. // Close metadata
  866. //
  867. m_Source.Close();
  868. for ( i = 0 ; i < m_dwTargets ; ++i )
  869. {
  870. if ( m_bmIsRemote.GetFlag( i ) )
  871. {
  872. m_pTargets[i]->Close();
  873. }
  874. }
  875. //
  876. // Process queued update requests
  877. //
  878. if ( !ProcessQueuedRequest() )
  879. {
  880. hRes = RETURNCODETOHRESULT( GetLastError() );
  881. }
  882. //
  883. // Terminate target machine metadata objects
  884. //
  885. for ( i = 0 ; i < m_dwTargets ; ++i )
  886. {
  887. m_pTargets[i]->Terminate();
  888. }
  889. //
  890. // Scan for errors on targets
  891. //
  892. for ( fIsError = FALSE, i = 0 ; i < m_dwTargets ; ++i )
  893. {
  894. pdwResults[i] = m_TargetStatus.GetStatus( i );
  895. if ( pdwResults[i] )
  896. {
  897. fIsError = TRUE;
  898. }
  899. }
  900. if ( hRes == S_OK && m_fCancel )
  901. {
  902. hRes = RETURNCODETOHRESULT( ERROR_CANCELLED );
  903. }
  904. if ( hRes == S_OK &&
  905. fIsError )
  906. {
  907. hRes = E_FAIL;
  908. }
  909. Exit:
  910. //
  911. // Clean up session key seed
  912. //
  913. if ( fGotSeed )
  914. {
  915. DeleteKeySeed();
  916. }
  917. //
  918. // Terminate source machine metadata object
  919. //
  920. m_Source.Terminate();
  921. delete m_pRoot;
  922. m_pRoot = NULL;
  923. m_fInScan = FALSE;
  924. return hRes;
  925. }
  926. BOOL
  927. CMdIf::Init(
  928. LPSTR pszComputer
  929. )
  930. /*++
  931. Routine Description:
  932. Initialize metabase admin interface :
  933. get interface pointer, call Initialize()
  934. Arguments:
  935. pszComputer - computer name, NULL for local computer
  936. Returns:
  937. TRUE if success, otherwise FALSE
  938. --*/
  939. {
  940. IClassFactory * pcsfFactory;
  941. COSERVERINFO csiMachineName;
  942. HRESULT hresError;
  943. BOOL fSt = FALSE;
  944. WCHAR awchComputer[COMPUTER_CHARACTER_SIZE];
  945. WCHAR* pwchComputer = NULL;
  946. m_fModified = FALSE;
  947. //fill the structure for CoGetClassObject
  948. ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
  949. // csiMachineName.pAuthInfo = NULL;
  950. // csiMachineName.dwFlags = 0;
  951. // csiMachineName.pServerInfoExt = NULL;
  952. if ( pszComputer )
  953. {
  954. if ( !MultiByteToWideChar( CP_ACP,
  955. MB_PRECOMPOSED,
  956. pszComputer,
  957. -1,
  958. awchComputer,
  959. COMPUTER_CHARACTER_SIZE ) )
  960. {
  961. return FALSE;
  962. }
  963. pwchComputer = awchComputer;
  964. }
  965. csiMachineName.pwszName = pwchComputer;
  966. hresError = CoGetClassObject(
  967. CLSID_MSAdminBase_W,
  968. CLSCTX_SERVER,
  969. &csiMachineName,
  970. IID_IClassFactory,
  971. (void**) &pcsfFactory );
  972. if ( SUCCEEDED(hresError) )
  973. {
  974. hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase_W, (void **) &m_pcAdmCom);
  975. if (SUCCEEDED(hresError) )
  976. {
  977. fSt = TRUE;
  978. }
  979. else
  980. {
  981. SetLastError( HRESULTTOWIN32(hresError) );
  982. m_pcAdmCom = NULL;
  983. }
  984. pcsfFactory->Release();
  985. }
  986. else
  987. {
  988. if ( hresError == REGDB_E_CLASSNOTREG )
  989. {
  990. SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
  991. }
  992. else
  993. {
  994. SetLastError( HRESULTTOWIN32(hresError) );
  995. }
  996. m_pcAdmCom = NULL;
  997. }
  998. return fSt;
  999. }
  1000. BOOL
  1001. CMdIf::Open(
  1002. LPWSTR pszOpenPath,
  1003. DWORD dwPermission
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. Open path in metabase
  1008. Arguments:
  1009. pszOpenPath - path in metadata
  1010. dwPermission - metadata permission
  1011. Returns:
  1012. TRUE if success, otherwise FALSE
  1013. --*/
  1014. {
  1015. HRESULT hresError;
  1016. if (NULL == m_pcAdmCom)
  1017. {
  1018. SetLastError(E_NOINTERFACE);
  1019. return FALSE;
  1020. }
  1021. hresError = m_pcAdmCom->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1022. pszOpenPath, dwPermission, TIMEOUT_VALUE, &m_hmd );
  1023. if ( FAILED(hresError) )
  1024. {
  1025. m_hmd = NULL;
  1026. SetLastError( HRESULTTOWIN32(hresError) );
  1027. return FALSE;
  1028. }
  1029. return TRUE;
  1030. }
  1031. BOOL
  1032. CMdIf::Close(
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. Close path in metabase
  1037. Arguments:
  1038. None
  1039. Returns:
  1040. TRUE if success, otherwise FALSE
  1041. --*/
  1042. {
  1043. if ( m_pcAdmCom && m_hmd )
  1044. {
  1045. m_pcAdmCom->CloseKey(m_hmd);
  1046. }
  1047. m_hmd = NULL;
  1048. return TRUE;
  1049. }
  1050. BOOL
  1051. CMdIf::Terminate(
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. Terminate metabase admin interface :
  1056. call Terminate, release interface pointer
  1057. Arguments:
  1058. None
  1059. Returns:
  1060. TRUE if success, otherwise FALSE
  1061. --*/
  1062. {
  1063. if ( m_pcAdmCom )
  1064. {
  1065. if ( m_fModified )
  1066. {
  1067. m_pcAdmCom->SaveData();
  1068. }
  1069. m_pcAdmCom->Release();
  1070. m_hmd = NULL;
  1071. m_pcAdmCom = NULL;
  1072. }
  1073. return TRUE;
  1074. }
  1075. #if defined(ADMEX)
  1076. BOOL
  1077. CRpIf::Init(
  1078. LPSTR pszComputer,
  1079. CLSID* pClsid
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Initialize metabase admin interface :
  1084. get interface pointer, call Initialize()
  1085. Arguments:
  1086. pszComputer - computer name, NULL for local computer
  1087. Returns:
  1088. TRUE if success, otherwise FALSE
  1089. --*/
  1090. {
  1091. IClassFactory * pcsfFactory;
  1092. COSERVERINFO csiMachineName;
  1093. HRESULT hresError;
  1094. BOOL fSt = FALSE;
  1095. WCHAR awchComputer[COMPUTER_CHARACTER_SIZE];
  1096. WCHAR* pwchComputer = NULL;
  1097. //fill the structure for CoGetClassObject
  1098. ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
  1099. // csiMachineName.pAuthInfo = NULL;
  1100. // csiMachineName.dwFlags = 0;
  1101. // csiMachineName.pServerInfoExt = NULL;
  1102. if ( pszComputer )
  1103. {
  1104. if ( !MultiByteToWideChar( CP_ACP,
  1105. MB_PRECOMPOSED,
  1106. pszComputer,
  1107. -1,
  1108. awchComputer,
  1109. COMPUTER_CHARACTER_SIZE ) )
  1110. {
  1111. return FALSE;
  1112. }
  1113. pwchComputer = awchComputer;
  1114. }
  1115. csiMachineName.pwszName = pwchComputer;
  1116. hresError = CoGetClassObject(
  1117. *pClsid,
  1118. CLSCTX_SERVER,
  1119. &csiMachineName,
  1120. IID_IClassFactory,
  1121. (void**) &pcsfFactory );
  1122. if ( SUCCEEDED(hresError) )
  1123. {
  1124. hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminReplication, (void **) &m_pcAdmCom);
  1125. if (SUCCEEDED(hresError) )
  1126. {
  1127. fSt = TRUE;
  1128. }
  1129. else
  1130. {
  1131. SetLastError( HRESULTTOWIN32(hresError) );
  1132. m_pcAdmCom = NULL;
  1133. }
  1134. pcsfFactory->Release();
  1135. }
  1136. else
  1137. {
  1138. if ( hresError == REGDB_E_CLASSNOTREG )
  1139. {
  1140. SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
  1141. }
  1142. else
  1143. {
  1144. SetLastError( HRESULTTOWIN32(hresError) );
  1145. }
  1146. m_pcAdmCom = NULL;
  1147. }
  1148. return fSt;
  1149. }
  1150. BOOL
  1151. CRpIf::Terminate(
  1152. )
  1153. /*++
  1154. Routine Description:
  1155. Terminate metabase admin interface :
  1156. call Terminate, release interface pointer
  1157. Arguments:
  1158. None
  1159. Returns:
  1160. TRUE if success, otherwise FALSE
  1161. --*/
  1162. {
  1163. if ( m_pcAdmCom )
  1164. {
  1165. m_pcAdmCom->Release();
  1166. m_pcAdmCom = NULL;
  1167. }
  1168. return TRUE;
  1169. }
  1170. #endif
  1171. BOOL
  1172. CNodeDesc::Scan(
  1173. CSync* pSync
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. Scan subtree for nodes & properties
  1178. Signal each node availability for target synchronization
  1179. after scanning it.
  1180. Arguments:
  1181. pSync - synchronizer
  1182. Returns:
  1183. TRUE if success, otherwise FALSE
  1184. --*/
  1185. {
  1186. DWORD dwTarget;
  1187. if ( m_pSync->IsCancelled() )
  1188. {
  1189. return FALSE;
  1190. }
  1191. // get local props
  1192. if ( !m_Props.GetAll( m_pSync->GetSourceIf(), m_pszPath ) )
  1193. {
  1194. return FALSE;
  1195. }
  1196. m_pSync->IncrementSourceScan();
  1197. if ( !BuildChildObjectsList( m_pSync->GetSourceIf(), m_pszPath ) )
  1198. {
  1199. return FALSE;
  1200. }
  1201. m_Props.SetRefCount( m_pSync->GetTargetCount() ); // when 0, free props
  1202. for ( dwTarget = 0 ; dwTarget < m_pSync->GetTargetCount() ; ++dwTarget )
  1203. {
  1204. m_pSync->SignalWorkItem( dwTarget );
  1205. }
  1206. LIST_ENTRY* pSourceEntry;
  1207. CNodeDesc* pSourceDir;
  1208. //
  1209. // recursively scan children
  1210. //
  1211. for ( pSourceEntry = m_ChildHead.Flink;
  1212. pSourceEntry != &m_ChildHead ;
  1213. pSourceEntry = pSourceEntry->Flink )
  1214. {
  1215. pSourceDir = CONTAINING_RECORD( pSourceEntry,
  1216. CNodeDesc,
  1217. m_ChildList );
  1218. if ( !pSourceDir->Scan( pSync ) )
  1219. {
  1220. return FALSE;
  1221. }
  1222. }
  1223. return TRUE;
  1224. }
  1225. BOOL
  1226. CNodeDesc::ScanTarget(
  1227. DWORD dwTarget
  1228. )
  1229. /*++
  1230. Routine Description:
  1231. Scan target subtree for nodes and properties,
  1232. synchronizing with source. Wait for source scan
  1233. to be complete before synchronizing.
  1234. Arguments:
  1235. dwTarget - target ID
  1236. Returns:
  1237. TRUE if success, otherwise FALSE
  1238. --*/
  1239. {
  1240. m_pSync->WaitForWorkItem( dwTarget );
  1241. if ( m_pSync->IsCancelled() )
  1242. {
  1243. return FALSE;
  1244. }
  1245. if ( !DoWork( SCANMODE_SYNC_PROPS, dwTarget ) )
  1246. {
  1247. return FALSE;
  1248. }
  1249. LIST_ENTRY* pSourceEntry;
  1250. CNodeDesc* pSourceDir;
  1251. //
  1252. // recursively scan children
  1253. //
  1254. for ( pSourceEntry = m_ChildHead.Flink;
  1255. pSourceEntry != &m_ChildHead ;
  1256. pSourceEntry = pSourceEntry->Flink )
  1257. {
  1258. pSourceDir = CONTAINING_RECORD( pSourceEntry,
  1259. CNodeDesc,
  1260. m_ChildList );
  1261. if ( !pSourceDir->ScanTarget( dwTarget ) )
  1262. {
  1263. return FALSE;
  1264. }
  1265. }
  1266. return TRUE;
  1267. }
  1268. BOOL
  1269. CNodeDesc::DoWork(
  1270. SCANMODE sm,
  1271. DWORD dwTarget
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. synchronize target node with source node :
  1276. add/delete/update properties as needed,
  1277. add/delete nodes as needed.
  1278. Arguments:
  1279. sm - scan operation to perform
  1280. only SCANMODE_SYNC_PROPS is defined for now.
  1281. dwTarget - target ID
  1282. Returns:
  1283. TRUE if success, otherwise FALSE
  1284. --*/
  1285. {
  1286. CProps Props;
  1287. CNodeDesc TargetDir( m_pSync );
  1288. LIST_ENTRY* pSourceEntry;
  1289. CNodeDesc* pSourceDir;
  1290. LIST_ENTRY* pTargetEntry;
  1291. CNodeDesc* pTargetDir;
  1292. BOOL fMatch;
  1293. PMETADATA_RECORD pSourceProps;
  1294. PMETADATA_RECORD pTargetProps;
  1295. PBYTE pSourceData;
  1296. PBYTE pTargetData;
  1297. DWORD dwSourceProps;
  1298. DWORD dwTargetProps;
  1299. LPBYTE pbExists;
  1300. DWORD dwSourceObjs;
  1301. FILETIME ftSource;
  1302. FILETIME ftTarget;
  1303. BOOL fModified = FALSE;
  1304. UINT iS;
  1305. UINT iT;
  1306. BOOL fNeedUpdate;
  1307. BOOL fExists;
  1308. BOOL fDoNotSetTimeModif = FALSE;
  1309. //
  1310. // if target already in error, do not process request
  1311. //
  1312. if ( m_pSync->GetTargetError( dwTarget ) ||
  1313. m_pSync->IsLocal( dwTarget ) )
  1314. {
  1315. return TRUE;
  1316. }
  1317. switch ( sm )
  1318. {
  1319. case SCANMODE_SYNC_PROPS:
  1320. //
  1321. // Check date/time last modification.
  1322. // If identical on source & target, do not update
  1323. //
  1324. m_pSync->IncrementTargetScan( dwTarget );
  1325. if ( !(m_pSync->GetSourceIf())->GetLastChangeTime( m_pszPath, &ftSource ) )
  1326. {
  1327. return FALSE;
  1328. }
  1329. if ( m_pSync->GetTargetIf( dwTarget )->GetLastChangeTime( m_pszPath, &ftTarget ) )
  1330. {
  1331. if ( !memcmp( &ftSource, &ftTarget, sizeof(FILETIME) ) )
  1332. {
  1333. return TRUE;
  1334. }
  1335. }
  1336. else
  1337. {
  1338. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1339. return TRUE;
  1340. }
  1341. // get props on target, set / delete as appropriate
  1342. if ( Props.GetAll( m_pSync->GetTargetIf(dwTarget), m_pszPath ) )
  1343. {
  1344. pSourceProps = (PMETADATA_RECORD)m_Props.GetProps();
  1345. dwSourceProps = m_Props.GetPropsCount();
  1346. dwTargetProps = Props.GetPropsCount();
  1347. if ( !(pbExists = (LPBYTE)LocalAlloc( LMEM_FIXED, dwTargetProps )) )
  1348. {
  1349. return FALSE;
  1350. }
  1351. memset( pbExists, '\x0', dwTargetProps );
  1352. for ( iS = 0 ; iS < dwSourceProps ; ++iS,++pSourceProps )
  1353. {
  1354. pSourceData = (LPBYTE)m_Props.GetProps() + (UINT_PTR)pSourceProps->pbMDData;
  1355. pTargetProps = (PMETADATA_RECORD)Props.GetProps();
  1356. fNeedUpdate = TRUE;
  1357. fExists = FALSE;
  1358. for ( iT = 0 ; iT < dwTargetProps ; ++iT,++pTargetProps )
  1359. {
  1360. if ( pSourceProps->dwMDIdentifier ==
  1361. pTargetProps->dwMDIdentifier )
  1362. {
  1363. pbExists[ iT ] = '\x1';
  1364. pTargetData = (LPBYTE)Props.GetProps() + (UINT_PTR)pTargetProps->pbMDData;
  1365. if ( m_Props.IsNse( pSourceProps->dwMDIdentifier ) )
  1366. {
  1367. fNeedUpdate = m_Props.NseIsDifferent( pSourceProps->dwMDIdentifier, pSourceData, pSourceProps->dwMDDataLen, pTargetData, pTargetProps->dwMDDataLen, m_pszPath, dwTarget );
  1368. }
  1369. else if ( pSourceProps->dwMDDataType == pTargetProps->dwMDDataType &&
  1370. pSourceProps->dwMDUserType == pTargetProps->dwMDUserType )
  1371. {
  1372. fExists = TRUE;
  1373. if( pSourceProps->dwMDDataLen == pTargetProps->dwMDDataLen &&
  1374. !memcmp(pSourceData, pTargetData, pSourceProps->dwMDDataLen ) )
  1375. {
  1376. fNeedUpdate = FALSE;
  1377. }
  1378. else if ( pSourceProps->dwMDIdentifier == MD_SERVER_STATE ||
  1379. pSourceProps->dwMDIdentifier == MD_WIN32_ERROR ||
  1380. pSourceProps->dwMDIdentifier == MD_SERVER_COMMAND ||
  1381. pSourceProps->dwMDIdentifier == MD_CLUSTER_SERVER_COMMAND ||
  1382. pSourceProps->dwMDIdentifier == MD_ANONYMOUS_USER_NAME ||
  1383. pSourceProps->dwMDIdentifier == MD_ANONYMOUS_PWD ||
  1384. pSourceProps->dwMDIdentifier == MD_WAM_USER_NAME ||
  1385. pSourceProps->dwMDIdentifier == MD_WAM_PWD
  1386. )
  1387. {
  1388. fNeedUpdate = FALSE;
  1389. }
  1390. #if defined(METADATA_LOCAL_MACHINE_ONLY)
  1391. else if ( pSourceProps->dwMDAttributes
  1392. & METADATA_LOCAL_MACHINE_ONLY )
  1393. {
  1394. fNeedUpdate = FALSE;
  1395. }
  1396. #endif
  1397. }
  1398. }
  1399. }
  1400. if ( fNeedUpdate )
  1401. {
  1402. if ( m_Props.IsNse( pSourceProps->dwMDIdentifier ) )
  1403. {
  1404. if ( !m_pSync->QueueRequest(
  1405. pSourceProps->dwMDIdentifier,
  1406. m_pszPath,
  1407. dwTarget,
  1408. &ftSource ) )
  1409. {
  1410. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1411. }
  1412. else
  1413. {
  1414. //
  1415. // differ updating time last modif
  1416. // until NSE update processed
  1417. //
  1418. fDoNotSetTimeModif = TRUE;
  1419. }
  1420. }
  1421. else
  1422. {
  1423. METADATA_RECORD md;
  1424. md = *pSourceProps;
  1425. if ( !(m_pSync->QueryFlags() & MD_SYNC_FLAG_REPLICATE_AUTOSTART) &&
  1426. md.dwMDIdentifier == MD_SERVER_AUTOSTART )
  1427. {
  1428. if ( fExists )
  1429. {
  1430. fNeedUpdate = FALSE;
  1431. }
  1432. else
  1433. {
  1434. //
  1435. // create as FALSE ( server won't autostart )
  1436. //
  1437. pSourceData = (LPBYTE)&g_dwFalse;
  1438. md.dwMDDataLen = sizeof(DWORD);
  1439. md.dwMDDataType = DWORD_METADATA;
  1440. }
  1441. }
  1442. if ( !(m_pSync->QueryFlags() & MD_SYNC_FLAG_DONT_PRESERVE_IP_BINDINGS) &&
  1443. (md.dwMDIdentifier == MD_SERVER_BINDINGS ||
  1444. md.dwMDIdentifier == MD_SECURE_BINDINGS) )
  1445. {
  1446. if ( fExists )
  1447. {
  1448. fNeedUpdate = FALSE;
  1449. }
  1450. }
  1451. if ( fNeedUpdate )
  1452. {
  1453. if ( !m_pSync->GetTargetIf(dwTarget)->SetData( m_pszPath, &md, pSourceData ) )
  1454. {
  1455. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1456. }
  1457. }
  1458. }
  1459. m_pSync->SetModified( dwTarget );
  1460. fModified = TRUE;
  1461. }
  1462. }
  1463. // delete prop not in src
  1464. pTargetProps = (PMETADATA_RECORD)Props.GetProps();
  1465. for ( iT = 0 ; iT < dwTargetProps ; ++iT,++pTargetProps )
  1466. {
  1467. if ( !pbExists[ iT ] )
  1468. {
  1469. if ( !m_pSync->GetTargetIf(dwTarget)->DeleteProp( m_pszPath, pTargetProps ) )
  1470. {
  1471. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1472. }
  1473. m_pSync->SetModified( dwTarget );
  1474. fModified = TRUE;
  1475. }
  1476. }
  1477. LocalFree( pbExists );
  1478. }
  1479. // enum objects on target, delete sub-tree as appropriate
  1480. if ( TargetDir.BuildChildObjectsList( m_pSync->GetTargetIf(dwTarget), m_pszPath ) )
  1481. {
  1482. for ( dwSourceObjs = 0, pSourceEntry = m_ChildHead.Flink;
  1483. pSourceEntry != &m_ChildHead ;
  1484. ++dwSourceObjs, pSourceEntry = pSourceEntry->Flink )
  1485. {
  1486. }
  1487. if ( !(pbExists = (LPBYTE)LocalAlloc( LMEM_FIXED, dwSourceObjs )) )
  1488. {
  1489. return FALSE;
  1490. }
  1491. memset( pbExists, '\x0', dwSourceObjs );
  1492. for ( pTargetEntry = TargetDir.m_ChildHead.Flink;
  1493. pTargetEntry != &TargetDir.m_ChildHead ;
  1494. pTargetEntry = pTargetEntry->Flink )
  1495. {
  1496. pTargetDir = CONTAINING_RECORD( pTargetEntry,
  1497. CNodeDesc,
  1498. m_ChildList );
  1499. fMatch = FALSE;
  1500. for ( iS = 0, pSourceEntry = m_ChildHead.Flink;
  1501. pSourceEntry != &m_ChildHead ;
  1502. ++iS, pSourceEntry = pSourceEntry->Flink )
  1503. {
  1504. pSourceDir = CONTAINING_RECORD( pSourceEntry,
  1505. CNodeDesc,
  1506. m_ChildList );
  1507. if ( !_wcsicmp( pTargetDir->GetPath(), pSourceDir->GetPath() ) )
  1508. {
  1509. pbExists[ iS ] = '\x1';
  1510. fMatch = TRUE;
  1511. break;
  1512. }
  1513. }
  1514. if ( !fMatch )
  1515. {
  1516. if ( !m_pSync->GetTargetIf(dwTarget)->DeleteSubTree( pTargetDir->GetPath() ) )
  1517. {
  1518. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1519. }
  1520. m_pSync->SetModified( dwTarget );
  1521. fModified = TRUE;
  1522. }
  1523. }
  1524. //
  1525. // Add node if does not exist on target
  1526. //
  1527. for ( iS = 0, pSourceEntry = m_ChildHead.Flink;
  1528. pSourceEntry != &m_ChildHead ;
  1529. ++iS, pSourceEntry = pSourceEntry->Flink )
  1530. {
  1531. if ( !pbExists[iS] )
  1532. {
  1533. pSourceDir = CONTAINING_RECORD( pSourceEntry,
  1534. CNodeDesc,
  1535. m_ChildList );
  1536. if ( !m_pSync->GetTargetIf(dwTarget)->AddNode( pSourceDir->GetPath() ) )
  1537. {
  1538. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1539. }
  1540. m_pSync->SetModified( dwTarget );
  1541. fModified = TRUE;
  1542. }
  1543. }
  1544. LocalFree( pbExists );
  1545. }
  1546. else
  1547. {
  1548. // not error if does not exist on target
  1549. }
  1550. if ( fModified &&
  1551. !fDoNotSetTimeModif &&
  1552. !m_pSync->GetTargetError( dwTarget ) &&
  1553. !m_pSync->GetTargetIf( dwTarget )->SetLastChangeTime( m_pszPath, &ftSource ) )
  1554. {
  1555. m_pSync->SetTargetError( dwTarget, GetLastError() );
  1556. }
  1557. if ( fModified )
  1558. {
  1559. m_pSync->IncrementTargetTouched( dwTarget );
  1560. }
  1561. m_Props.Dereference();
  1562. break;
  1563. }
  1564. return TRUE;
  1565. }
  1566. BOOL
  1567. CProps::NseIsDifferent(
  1568. DWORD dwId,
  1569. LPBYTE pSourceData,
  1570. DWORD dwSourceLen,
  1571. LPBYTE pTargetData,
  1572. DWORD dwTargetLen,
  1573. LPWSTR pszPath,
  1574. DWORD dwTarget
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. Check if two NSE properties are different
  1579. Arguments:
  1580. dwId - property ID
  1581. pSourceData - ptr to source data for this property
  1582. dwSourceLen - # of bytes in pSourceData
  1583. pTargetData - ptr to target data for this property
  1584. dwTargetLen - # of bytes in pTargetData
  1585. pszPath - path to property
  1586. dwTarget - target ID
  1587. Returns:
  1588. TRUE if properties different, FALSE if identical
  1589. --*/
  1590. {
  1591. switch ( dwId )
  1592. {
  1593. case MD_SERIAL_CERT11:
  1594. case MD_SERIAL_DIGEST:
  1595. //
  1596. // serialized format is (DWORD)len, string, then MD5 signature ( 16 bytes )
  1597. //
  1598. //
  1599. // skip string
  1600. //
  1601. if ( *(LPDWORD)pSourceData < dwSourceLen )
  1602. {
  1603. pSourceData += sizeof(DWORD) + *(LPDWORD)pSourceData;
  1604. }
  1605. if ( *(LPDWORD)pTargetData < dwTargetLen )
  1606. {
  1607. pTargetData += sizeof(DWORD) + *(LPDWORD)pTargetData;
  1608. }
  1609. //
  1610. // compare MD5 signature
  1611. //
  1612. return memcmp( pSourceData, pTargetData, 16 );
  1613. }
  1614. //
  1615. // Don't know how to handle, do not replicate
  1616. //
  1617. return FALSE;
  1618. }
  1619. CNseRequest::CNseRequest(
  1620. )
  1621. /*++
  1622. Routine Description:
  1623. NSE request constructor
  1624. Arguments:
  1625. None
  1626. Returns:
  1627. Nothing
  1628. --*/
  1629. {
  1630. m_pszPath = NULL;
  1631. m_pszModifPath = NULL;
  1632. m_pbData = NULL;
  1633. }
  1634. CNseRequest::~CNseRequest(
  1635. )
  1636. /*++
  1637. Routine Description:
  1638. NSE request destructor
  1639. Arguments:
  1640. None
  1641. Returns:
  1642. Nothing
  1643. --*/
  1644. {
  1645. if ( m_pszPath )
  1646. {
  1647. LocalFree( m_pszPath );
  1648. }
  1649. if ( m_pszModifPath )
  1650. {
  1651. LocalFree( m_pszModifPath );
  1652. }
  1653. if ( m_pszCreatePath )
  1654. {
  1655. LocalFree( m_pszCreatePath );
  1656. }
  1657. if ( m_pszCreateObject )
  1658. {
  1659. LocalFree( m_pszCreateObject );
  1660. }
  1661. if ( m_pbData )
  1662. {
  1663. LocalFree( m_pbData );
  1664. }
  1665. }
  1666. BOOL
  1667. CNseRequest::Init(
  1668. LPWSTR pszPath,
  1669. LPWSTR pszCreatePath,
  1670. LPWSTR pszCreateObject,
  1671. DWORD dwId,
  1672. DWORD dwTargetCount,
  1673. LPWSTR pszModifPath,
  1674. FILETIME* pftModif,
  1675. METADATA_RECORD* pMd
  1676. )
  1677. /*++
  1678. Routine Description:
  1679. Initialize NSE request
  1680. Arguments:
  1681. pszPath - NSE path to property
  1682. pszCreatePath - NSE path where to create object if open object fails
  1683. pszCreateObject - name of object to create if open object fails
  1684. dwId - property ID
  1685. dwTargetCount - # of potential targets
  1686. pszModifPath - path where to update last date/time modification
  1687. on success
  1688. pftModif - last date/time modification to set on success
  1689. pMD - metadata record to set on target
  1690. Returns:
  1691. Nothing
  1692. --*/
  1693. {
  1694. m_dwTargetCount = dwTargetCount;
  1695. m_dwId = dwId;
  1696. if ( !(m_pszPath = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszPath)+1)*sizeof(WCHAR) )) )
  1697. {
  1698. return FALSE;
  1699. }
  1700. wcscpy( m_pszPath, pszPath );
  1701. if ( !(m_pszModifPath = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszModifPath)+1)*sizeof(WCHAR) )) )
  1702. {
  1703. LocalFree( m_pszPath );
  1704. return FALSE;
  1705. }
  1706. wcscpy( m_pszModifPath, pszModifPath );
  1707. if ( !(m_pszCreatePath = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszCreatePath)+1)*sizeof(WCHAR) )) )
  1708. {
  1709. LocalFree( m_pszModifPath );
  1710. LocalFree( m_pszPath );
  1711. return FALSE;
  1712. }
  1713. wcscpy( m_pszCreatePath, pszCreatePath );
  1714. if ( !(m_pszCreateObject = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszCreateObject)+1)*sizeof(WCHAR) )) )
  1715. {
  1716. LocalFree( m_pszCreatePath );
  1717. LocalFree( m_pszModifPath );
  1718. LocalFree( m_pszPath );
  1719. return FALSE;
  1720. }
  1721. wcscpy( m_pszCreateObject, pszCreateObject );
  1722. m_ftModif = *pftModif;
  1723. m_md = *pMd;
  1724. return m_bmTarget.Init( dwTargetCount, FALSE );
  1725. }
  1726. BOOL
  1727. CNseRequest::Process(
  1728. CSync* pSync
  1729. )
  1730. /*++
  1731. Routine Description:
  1732. Process a NSE request :
  1733. replicate source property to designated targets
  1734. Arguments:
  1735. pSync - synchronizer
  1736. Returns:
  1737. TRUE if success, otherwise FALSE
  1738. --*/
  1739. {
  1740. CMdIf* pSource = pSync->GetSourceIf();
  1741. CMdIf* pTarget;
  1742. UINT i;
  1743. DWORD dwRequired;
  1744. int retry;
  1745. if ( !pSource )
  1746. {
  1747. SetLastError( ERROR_INVALID_PARAMETER );
  1748. return FALSE;
  1749. }
  1750. if ( pSource->Open( m_pszPath, METADATA_PERMISSION_READ ) )
  1751. {
  1752. m_md.pbMDData = NULL;
  1753. m_md.dwMDDataLen = 0;
  1754. if ( !pSource->GetData( L"", &m_md, NULL, &dwRequired) )
  1755. {
  1756. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  1757. {
  1758. if ( !(m_pbData = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) )
  1759. {
  1760. pSource->Close();
  1761. return FALSE;
  1762. }
  1763. m_md.pbMDData = m_pbData;
  1764. m_md.dwMDDataLen = dwRequired;
  1765. if ( !pSource->GetData( L"", &m_md, m_pbData, &dwRequired) )
  1766. {
  1767. pSource->Close();
  1768. return FALSE;
  1769. }
  1770. }
  1771. else
  1772. {
  1773. pSource->Close();
  1774. return FALSE;
  1775. }
  1776. }
  1777. for ( i = 0 ; i < m_dwTargetCount ; ++i )
  1778. {
  1779. if ( m_bmTarget.GetFlag(i) &&
  1780. !pSync->GetTargetError( i ) )
  1781. {
  1782. pTarget = pSync->GetTargetIf( i );
  1783. //
  1784. // Insure object exist by creating it
  1785. // Open path w/o last component, Add last component
  1786. //
  1787. LPWSTR pLast = m_pszPath + wcslen( m_pszPath ) - 1;
  1788. while ( *pLast != L'/' )
  1789. {
  1790. --pLast;
  1791. }
  1792. *pLast = L'\0';
  1793. if ( pTarget->Open( m_pszPath, METADATA_PERMISSION_WRITE ) )
  1794. {
  1795. pTarget->AddNode( pLast + 1 );
  1796. pTarget->Close();
  1797. }
  1798. *pLast = L'/';
  1799. //
  1800. // Set serialized data
  1801. //
  1802. if ( pTarget->Open( m_pszPath, METADATA_PERMISSION_WRITE ) )
  1803. {
  1804. if ( !pTarget->SetData( L"", &m_md, m_pbData ) )
  1805. {
  1806. pSync->SetTargetError( i, GetLastError() );
  1807. }
  1808. pSync->SetModified( i );
  1809. pTarget->Close();
  1810. //
  1811. // set date/time last modif
  1812. //
  1813. if ( !pSync->GetTargetError( i ) &&
  1814. pTarget->Open( L"/LM", METADATA_PERMISSION_WRITE ) )
  1815. {
  1816. if ( !pTarget->SetLastChangeTime( m_pszModifPath, &m_ftModif ) )
  1817. {
  1818. pSync->SetTargetError( i, GetLastError() );
  1819. }
  1820. pTarget->Close();
  1821. }
  1822. break;
  1823. }
  1824. else
  1825. {
  1826. pSync->SetTargetError( i, GetLastError() );
  1827. break;
  1828. }
  1829. }
  1830. }
  1831. pSource->Close();
  1832. }
  1833. else
  1834. {
  1835. return FALSE;
  1836. }
  1837. return TRUE;
  1838. }
  1839. BOOL
  1840. CSync::ProcessQueuedRequest(
  1841. )
  1842. /*++
  1843. Routine Description:
  1844. Process all queued NSE requests
  1845. Arguments:
  1846. None
  1847. Returns:
  1848. TRUE if success, otherwise FALSE
  1849. --*/
  1850. {
  1851. LIST_ENTRY* pChild;
  1852. CNseRequest* pReq;
  1853. BOOL fSt = TRUE;
  1854. while ( !IsListEmpty( &m_QueuedRequestsHead ))
  1855. {
  1856. pReq = CONTAINING_RECORD( m_QueuedRequestsHead.Flink,
  1857. CNseRequest,
  1858. m_QueuedRequestsList );
  1859. if ( IsCancelled() ||
  1860. !pReq->Process( this ) )
  1861. {
  1862. fSt = FALSE;
  1863. }
  1864. RemoveEntryList( &pReq->m_QueuedRequestsList );
  1865. delete pReq;
  1866. }
  1867. return fSt;
  1868. }
  1869. BOOL
  1870. CSync::QueueRequest(
  1871. DWORD dwId,
  1872. LPWSTR pszPath,
  1873. DWORD dwTarget,
  1874. FILETIME* pftModif
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Queue a NSE request
  1879. We cannot process then inline as we need to open a different
  1880. path to NSE, which will open a path in metabase space, which will
  1881. conflict with the current open.
  1882. So we queue requests to be processed after closing all opened
  1883. metabase paths.
  1884. Arguments:
  1885. dwId - property ID
  1886. pszPath - NSE path
  1887. dwTarget - target ID
  1888. pftModif - date/time last modification to set on targets if success
  1889. Returns:
  1890. TRUE if success, otherwise FALSE
  1891. --*/
  1892. {
  1893. WCHAR achPath[MAX_PATH];
  1894. WCHAR achCreatePath[MAX_PATH];
  1895. WCHAR achCreateObject[MAX_PATH];
  1896. DWORD dwL = wcslen( pszPath );
  1897. BOOL fSt = TRUE;
  1898. DWORD dwSerialId;
  1899. METADATA_RECORD md;
  1900. memcpy( achPath, L"/LM", sizeof(L"/LM") - 1*sizeof(WCHAR) );
  1901. memcpy( (LPBYTE)achPath + sizeof(L"/LM") - 1*sizeof(WCHAR), pszPath, dwL*sizeof(WCHAR) );
  1902. dwL += wcslen(L"/LM");
  1903. memcpy( achCreatePath, achPath, dwL*sizeof(WCHAR) );
  1904. memset( &md, '\0', sizeof(md) );
  1905. md.dwMDAttributes = 0;
  1906. md.dwMDUserType = IIS_MD_UT_SERVER;
  1907. md.dwMDDataType = BINARY_METADATA;
  1908. md.dwMDDataTag = 0;
  1909. switch ( dwId )
  1910. {
  1911. case MD_SERIAL_CERT11:
  1912. wcscpy( achPath+dwL, L"/<nsepm>/Cert11" );
  1913. wcscpy( achCreatePath+dwL, L"/<nsepm>" );
  1914. wcscpy( achCreateObject, L"Cert11" );
  1915. dwSerialId = MD_SERIAL_ALL_CERT11;
  1916. md.dwMDIdentifier = dwSerialId;
  1917. break;
  1918. case MD_SERIAL_DIGEST:
  1919. wcscpy( achPath+dwL, L"/<nsepm>/Digest" );
  1920. wcscpy( achCreatePath+dwL, L"/<nsepm>" );
  1921. wcscpy( achCreateObject, L"Digest" );
  1922. dwSerialId = MD_SERIAL_ALL_DIGEST;
  1923. md.dwMDIdentifier = dwSerialId;
  1924. break;
  1925. default:
  1926. return FALSE;
  1927. }
  1928. EnterCriticalSection( &m_csQueuedRequestsList );
  1929. // locate path in list, add entry if not exists
  1930. // set target bit
  1931. LIST_ENTRY* pEntry;
  1932. CNseRequest* pReq;
  1933. BOOL fFound = FALSE;
  1934. for ( pEntry = m_QueuedRequestsHead.Flink;
  1935. pEntry != &m_QueuedRequestsHead ;
  1936. pEntry = pEntry->Flink )
  1937. {
  1938. pReq = CONTAINING_RECORD( pEntry,
  1939. CNseRequest,
  1940. m_QueuedRequestsList );
  1941. if ( pReq->Match( achPath, dwSerialId ) )
  1942. {
  1943. fFound = TRUE;
  1944. break;
  1945. }
  1946. }
  1947. if ( !fFound )
  1948. {
  1949. if ( !(pReq = new CNseRequest()) )
  1950. {
  1951. fSt = FALSE;
  1952. }
  1953. else if ( !pReq->Init( achPath,
  1954. achCreatePath,
  1955. achCreateObject,
  1956. dwSerialId,
  1957. GetTargetCount(),
  1958. pszPath,
  1959. pftModif,
  1960. &md ) )
  1961. {
  1962. delete pReq;
  1963. fSt = FALSE;
  1964. }
  1965. else
  1966. {
  1967. InsertHeadList( &m_QueuedRequestsHead, &pReq->m_QueuedRequestsList );
  1968. }
  1969. }
  1970. if ( fSt )
  1971. {
  1972. pReq->AddTarget( dwTarget );
  1973. }
  1974. LeaveCriticalSection( &m_csQueuedRequestsList );
  1975. return fSt;
  1976. }
  1977. BOOL
  1978. CSync::ProcessAdminExReplication(
  1979. LPWSTR pszClsids,
  1980. LPSTR pszTargets,
  1981. DWORD dwPhase
  1982. )
  1983. /*++
  1984. Routine Description:
  1985. Process replication using admin extensions
  1986. Arguments:
  1987. pszClsids - multi-sz of ClsIds for admin extensions
  1988. pszTargets - multi-sz of target computers ( computer names )
  1989. dwPhase - phase 1 or 2
  1990. Returns:
  1991. TRUE if success, otherwise FALSE
  1992. --*/
  1993. {
  1994. #if defined(ADMEX)
  1995. CRpIf **pTargets;
  1996. CRpIf Source;
  1997. UINT i;
  1998. LPWSTR pw;
  1999. LPSTR p;
  2000. BOOL fSt = TRUE;
  2001. BUFFER buSourceSignature;
  2002. BUFFER buTargetSignature;
  2003. BUFFER buSerialize;
  2004. DWORD dwSourceSignature;
  2005. DWORD dwTargetSignature;
  2006. DWORD dwSerialize;
  2007. BOOL fHasSource;
  2008. CLSID clsid;
  2009. DWORD iC;
  2010. BOOL fFirstPhase2Clsid = TRUE;
  2011. HRESULT hr;
  2012. if ( !(pTargets = (CRpIf**)LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, sizeof(CRpIf*)*m_dwTargets)) )
  2013. {
  2014. return FALSE;
  2015. }
  2016. for ( i = 0, p = pszTargets ; *p ; p += strlen(p)+1, ++i )
  2017. {
  2018. if ( m_bmIsRemote.GetFlag( i ) )
  2019. {
  2020. if ( !(pTargets[i] = new CRpIf()) )
  2021. {
  2022. goto Exit;
  2023. }
  2024. }
  2025. }
  2026. // build TargetSignatureMismatch array if phase 1
  2027. if ( dwPhase == AER_PHASE1 )
  2028. {
  2029. for ( pw = pszClsids, iC = 0 ; *pw ; pw += wcslen(pw)+1, ++iC )
  2030. {
  2031. }
  2032. m_bmTargetSignatureMismatch.Init( m_dwTargets * iC, FALSE );
  2033. }
  2034. // enumerate all CLSID for extensions
  2035. for ( pw = pszClsids, iC = 0 ; *pw ; pw += wcslen(pw)+1, ++iC )
  2036. {
  2037. // if Source.Init fails skip to next one : replication I/F not available for
  2038. // this CLSID
  2039. if ( SUCCEEDED( CLSIDFromString( pw, &clsid ) ) &&
  2040. Source.Init( NULL, &clsid ) )
  2041. {
  2042. fHasSource = FALSE;
  2043. // for each one, get source signature
  2044. if ( !Source.GetSignature( &buSourceSignature, &dwSourceSignature ) )
  2045. {
  2046. fSt = FALSE;
  2047. goto Exit;
  2048. }
  2049. // enumerate targets, get signature, if <> source Serialize if not already available
  2050. // and propagate to target
  2051. for ( i = 0, p = pszTargets ; *p ; p += strlen(p)+1, ++i )
  2052. {
  2053. if ( IsCancelled() )
  2054. {
  2055. fSt = FALSE;
  2056. goto Exit;
  2057. }
  2058. if ( pTargets[i] &&
  2059. !GetTargetError( i ) &&
  2060. pTargets[i]->Init( p, &clsid ) )
  2061. {
  2062. switch ( dwPhase )
  2063. {
  2064. case AER_PHASE1:
  2065. if ( !pTargets[i]->GetSignature( &buTargetSignature,
  2066. &dwTargetSignature ) )
  2067. {
  2068. SetTargetError( i, GetLastError() );
  2069. }
  2070. else if ( dwSourceSignature != dwTargetSignature ||
  2071. memcmp( buSourceSignature.QueryPtr(),
  2072. buTargetSignature.QueryPtr(),
  2073. dwTargetSignature ) )
  2074. {
  2075. if ( !fHasSource &&
  2076. !Source.Serialize( &buSerialize, &dwSerialize ) )
  2077. {
  2078. fSt = FALSE;
  2079. goto Exit;
  2080. }
  2081. fHasSource = TRUE;
  2082. SetTargetSignatureMismatch( i, iC, TRUE );
  2083. if ( !Source.Propagate( p, strlen(p)+1 ) )
  2084. {
  2085. SetTargetError( i, GetLastError() );
  2086. }
  2087. else if( !pTargets[i]->DeSerialize( &buSerialize, dwSerialize ) )
  2088. {
  2089. SetTargetError( i, GetLastError() );
  2090. }
  2091. }
  2092. break;
  2093. case AER_PHASE2:
  2094. if ( fFirstPhase2Clsid )
  2095. {
  2096. if ( FAILED( hr = MTS_Propagate2( strlen(p)+1, (PBYTE)p, TRUE ) ) )
  2097. {
  2098. SetTargetError( i, HRESULTTOWIN32(hr) );
  2099. }
  2100. }
  2101. if ( !Source.Propagate2( p,
  2102. strlen(p)+1,
  2103. GetTargetSignatureMismatch( i, iC ) ) )
  2104. {
  2105. SetTargetError( i, GetLastError() );
  2106. }
  2107. if ( QueryFlags() & MD_SYNC_FLAG_CHECK_ADMINEX_SIGNATURE )
  2108. {
  2109. if ( !pTargets[i]->GetSignature( &buTargetSignature, &dwTargetSignature ) )
  2110. {
  2111. SetTargetError( i, GetLastError() );
  2112. }
  2113. else if ( dwSourceSignature != dwTargetSignature ||
  2114. memcmp( buSourceSignature.QueryPtr(), buTargetSignature.QueryPtr(), dwTargetSignature ) )
  2115. {
  2116. SetTargetError( i, ERROR_REVISION_MISMATCH );
  2117. }
  2118. }
  2119. break;
  2120. }
  2121. pTargets[i]->Terminate();
  2122. }
  2123. }
  2124. Source.Terminate();
  2125. }
  2126. fFirstPhase2Clsid = FALSE;
  2127. }
  2128. Exit:
  2129. Source.Terminate();
  2130. if ( pTargets )
  2131. {
  2132. for ( i = 0 ; i < m_dwTargets ; ++i )
  2133. {
  2134. if ( pTargets[i] )
  2135. {
  2136. if ( m_bmIsRemote.GetFlag( i ) )
  2137. {
  2138. pTargets[i]->Terminate();
  2139. }
  2140. delete pTargets[i];
  2141. }
  2142. }
  2143. LocalFree( pTargets );
  2144. }
  2145. return fSt;
  2146. #else
  2147. return TRUE;
  2148. #endif
  2149. }
  2150. HRESULT
  2151. MdSync::Synchronize(
  2152. LPSTR pszTargets,
  2153. LPDWORD pdwResults,
  2154. DWORD dwFlags,
  2155. LPDWORD pStat
  2156. )
  2157. /*++
  2158. Routine Description:
  2159. Entry point for synchronize COM method
  2160. Arguments:
  2161. pszTargets - multisz of target computer names
  2162. can include local computer, will be ignored during synchro
  2163. pdwResults - updated with error code for each target
  2164. dwFlags - flags, no flag defined for now. Should be 0.
  2165. pStat - ptr to stat struct
  2166. Returns:
  2167. status of request
  2168. --*/
  2169. {
  2170. return m_Sync.Sync( pszTargets, pdwResults, dwFlags, (SYNC_STAT*)pStat );
  2171. }
  2172. HRESULT
  2173. MdSync::Cancel(
  2174. )
  2175. /*++
  2176. Routine Description:
  2177. Entry point for cancel COM method
  2178. Arguments:
  2179. None
  2180. Returns:
  2181. status of request
  2182. --*/
  2183. {
  2184. return m_Sync.Cancel();
  2185. }
  2186. HRESULT
  2187. MTS_Propagate2
  2188. (
  2189. /* [in] */ DWORD dwBufferSize,
  2190. /* [size_is][in] */ unsigned char __RPC_FAR *pszBuffer,
  2191. /* [in] */ DWORD dwSignatureMismatch
  2192. )
  2193. {
  2194. HRESULT hr = NOERROR;
  2195. BSTR bstrSourceMachineName = NULL;
  2196. BSTR bstrTargetMachineName = NULL;
  2197. CHAR pszComputerName[MAX_COMPUTERNAME_LENGTH+1];
  2198. DWORD cch = MAX_COMPUTERNAME_LENGTH+1;
  2199. //pszBuffer Contains TargetMachineName(ANSI)
  2200. DBG_ASSERT(pszBuffer);
  2201. if ((BOOL)dwSignatureMismatch == FALSE)
  2202. {
  2203. DBGPRINTF((DBG_CONTEXT, "Signature is identical, MTS replication is not triggered.\n"));
  2204. return hr;
  2205. }
  2206. if (GetComputerName(pszComputerName, &cch))
  2207. {
  2208. WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
  2209. DWORD dwSuccess = 0;
  2210. dwSuccess = MultiByteToWideChar(0, 0, pszComputerName, -1, wszMachineName, MAX_COMPUTERNAME_LENGTH+1);
  2211. DBG_ASSERT(dwSuccess);
  2212. bstrSourceMachineName = SysAllocString(wszMachineName);
  2213. dwSuccess = MultiByteToWideChar(0, 0, (LPCSTR)pszBuffer, dwBufferSize, wszMachineName, MAX_COMPUTERNAME_LENGTH+1);
  2214. DBG_ASSERT(dwSuccess);
  2215. bstrTargetMachineName = SysAllocString(wszMachineName);
  2216. }
  2217. else
  2218. {
  2219. hr = HRESULT_FROM_WIN32(GetLastError());
  2220. DBGPRINTF((DBG_CONTEXT, "GetComputerName failed, hr = %08x\n",
  2221. hr));
  2222. }
  2223. if (SUCCEEDED(hr))
  2224. {
  2225. ICOMReplicate* piReplCat = NULL;
  2226. DBG_ASSERT(bstrSourceMachineName != NULL && bstrTargetMachineName != NULL);
  2227. hr = CoCreateInstance(CLSID_ReplicateCatalog,
  2228. NULL,
  2229. CLSCTX_INPROC_SERVER,
  2230. IID_ICOMReplicate,
  2231. (void**)&piReplCat);
  2232. if (SUCCEEDED(hr))
  2233. {
  2234. DBG_ASSERT(piReplCat);
  2235. //
  2236. // For now, just call the replication methods in a row.
  2237. //
  2238. //
  2239. // EBK 5/8/2000 Whistler #83172
  2240. // Removed bug comment from this. According to NT Bug 37371
  2241. // the best solution we came up with is the solution that is implemented
  2242. // here, so no more work or investigation is required.
  2243. //
  2244. // Replication of the iis com apps is not working. The problem
  2245. // is that com will not replicate iis applciations unless we
  2246. // tell it to (using the COMREPL_OPTION_REPLICATE_IIS_APPS flag).
  2247. // But if we tell it to replicate our apps, then com requires
  2248. // that the activation identity (IWAM_*) be the same on both
  2249. // machines. In order to do that we would need to replicate the
  2250. // IWAM_ account. There are a number of problems with this, not
  2251. // the least of which is encrypting the password during transfer.
  2252. // So to get this working at least reasonably well, I'm going to
  2253. // continue passing 0 here. And delete/recreate the isolated
  2254. // apps on the target in wamreg during the first phase of
  2255. // replication.
  2256. //
  2257. // See NT Bug 378371 for more details
  2258. //
  2259. hr = piReplCat->Initialize( bstrSourceMachineName, 0 );
  2260. if ( FAILED( hr ) )
  2261. {
  2262. DBGPRINTF(( DBG_CONTEXT,
  2263. "Initialize() failed with hr = %08x\n",
  2264. hr ));
  2265. piReplCat->Release();
  2266. goto Finished;
  2267. }
  2268. hr = piReplCat->ExportSourceCatalogFiles();
  2269. if ( FAILED( hr ) )
  2270. {
  2271. DBGPRINTF(( DBG_CONTEXT,
  2272. "ExportSourceCatalogFiles() failed with hr = %08x\n",
  2273. hr ));
  2274. piReplCat->CleanupSourceShares();
  2275. piReplCat->Release();
  2276. goto Finished;
  2277. }
  2278. hr = piReplCat->CopyFilesToTarget( bstrTargetMachineName );
  2279. if ( FAILED( hr ) )
  2280. {
  2281. DBGPRINTF(( DBG_CONTEXT,
  2282. "CopyCatalogFilesToTarget() failed with hr = %08x\n",
  2283. hr ));
  2284. piReplCat->CleanupSourceShares();
  2285. piReplCat->Release();
  2286. goto Finished;
  2287. }
  2288. hr = piReplCat->InstallTarget( bstrTargetMachineName );
  2289. if (FAILED(hr))
  2290. {
  2291. DBGPRINTF(( DBG_CONTEXT,
  2292. "InstallCatalogOnTarget() failed with hr = %08x\n",
  2293. hr ));
  2294. piReplCat->CleanupSourceShares();
  2295. piReplCat->Release();
  2296. goto Finished;
  2297. }
  2298. piReplCat->CleanupSourceShares();
  2299. piReplCat->Release();
  2300. }
  2301. else
  2302. {
  2303. DBGPRINTF((DBG_CONTEXT, "Failed to CoCreateInstance of CLSID_ReplicateCatalog, hr = %08x\n",
  2304. hr));
  2305. }
  2306. }
  2307. Finished:
  2308. if (bstrSourceMachineName)
  2309. {
  2310. SysFreeString(bstrSourceMachineName);
  2311. bstrSourceMachineName = NULL;
  2312. }
  2313. if (bstrTargetMachineName)
  2314. {
  2315. SysFreeString(bstrTargetMachineName);
  2316. bstrTargetMachineName = NULL;
  2317. }
  2318. return hr;
  2319. }