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.

722 lines
23 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. repl.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) 06-Jan-1995
  8. Revision History:
  9. Jeff Parham (jeffparh) 05-Dec-1995
  10. o Added replication of certificate database and secure service list.
  11. o Log failure to connect during replication only if the target server
  12. is running a build in which license server should be available (i.e.,
  13. 1057 (3.51) or greater). If the target server does not support
  14. license server, log a message to that effect only once.
  15. --*/
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <dsgetdc.h>
  21. #include "debug.h"
  22. #include "llsutil.h"
  23. #include <llsapi.h>
  24. #include "llssrv.h"
  25. #include "mapping.h"
  26. #include "msvctbl.h"
  27. #include "svctbl.h"
  28. #include "perseat.h"
  29. #include "server.h"
  30. #include "repl.h"
  31. #include "llsrpc_s.h"
  32. #include "pack.h"
  33. #include "llsevent.h"
  34. #include "certdb.h"
  35. #include "registry.h"
  36. #include <strsafe.h> //include last
  37. HANDLE ReplicationEvent;
  38. volatile HANDLE LlsRPCHandle = NULL; // Make sure it's reread after we enter critsec
  39. PLLS_REPL_CONNECT_W pLlsReplConnect = NULL;
  40. PLLS_REPL_CLOSE pLlsReplClose = NULL;
  41. PLLS_FREE_MEMORY pLlsFreeMemory = NULL;
  42. PLLS_REPLICATION_REQUEST_W pLlsReplicationRequestW = NULL;
  43. PLLS_REPLICATION_SERVER_ADD_W pLlsReplicationServerAddW = NULL;
  44. PLLS_REPLICATION_SERVER_SERVICE_ADD_W pLlsReplicationServerServiceAddW = NULL;
  45. PLLS_REPLICATION_SERVICE_ADD_W pLlsReplicationServiceAddW = NULL;
  46. PLLS_REPLICATION_USER_ADD_W pLlsReplicationUserAddW = NULL;
  47. PLLS_CAPABILITY_IS_SUPPORTED pLlsCapabilityIsSupported = NULL;
  48. PLLS_REPLICATION_CERT_DB_ADD_W pLlsReplicationCertDbAddW = NULL;
  49. PLLS_REPLICATION_PRODUCT_SECURITY_ADD_W pLlsReplicationProductSecurityAddW = NULL;
  50. PLLS_REPLICATION_USER_ADD_EX_W pLlsReplicationUserAddExW = NULL;
  51. PLLS_CONNECT_W pLlsConnectW = NULL;
  52. PLLS_CLOSE pLlsClose = NULL;
  53. PLLS_LICENSE_ADD_W pLlsLicenseAddW = NULL;
  54. NTSTATUS
  55. ReplicationInitDelayed ()
  56. {
  57. NTSTATUS Status = NOERROR;
  58. if (LlsRPCHandle != NULL)
  59. {
  60. return NOERROR;
  61. }
  62. RtlEnterCriticalSection(&g_csLock);
  63. if (LlsRPCHandle == NULL)
  64. {
  65. //
  66. // Open up our RPC DLL and init our function references.
  67. //
  68. LlsRPCHandle = LoadLibrary(TEXT("LLSRPC.DLL"));
  69. if (LlsRPCHandle != NULL) {
  70. pLlsReplConnect = (PLLS_REPL_CONNECT_W)GetProcAddress(LlsRPCHandle, ("LlsReplConnectW"));
  71. pLlsReplClose = (PLLS_REPL_CLOSE)GetProcAddress(LlsRPCHandle, ("LlsReplClose"));
  72. pLlsFreeMemory = (PLLS_FREE_MEMORY)GetProcAddress(LlsRPCHandle, ("LlsFreeMemory"));
  73. pLlsReplicationRequestW = (PLLS_REPLICATION_REQUEST_W)GetProcAddress(LlsRPCHandle, ("LlsReplicationRequestW"));
  74. pLlsReplicationServerAddW = (PLLS_REPLICATION_SERVER_ADD_W)GetProcAddress(LlsRPCHandle, ("LlsReplicationServerAddW"));
  75. pLlsReplicationServerServiceAddW = (PLLS_REPLICATION_SERVER_SERVICE_ADD_W)GetProcAddress(LlsRPCHandle, ("LlsReplicationServerServiceAddW"));
  76. pLlsReplicationServiceAddW = (PLLS_REPLICATION_SERVICE_ADD_W)GetProcAddress(LlsRPCHandle, ("LlsReplicationServiceAddW"));
  77. pLlsReplicationUserAddW = (PLLS_REPLICATION_USER_ADD_W)GetProcAddress(LlsRPCHandle, ("LlsReplicationUserAddW"));
  78. pLlsReplicationCertDbAddW = (PLLS_REPLICATION_CERT_DB_ADD_W) GetProcAddress(LlsRPCHandle, ("LlsReplicationCertDbAddW"));
  79. pLlsReplicationProductSecurityAddW = (PLLS_REPLICATION_PRODUCT_SECURITY_ADD_W) GetProcAddress(LlsRPCHandle, ("LlsReplicationProductSecurityAddW"));
  80. pLlsReplicationUserAddExW = (PLLS_REPLICATION_USER_ADD_EX_W) GetProcAddress(LlsRPCHandle, ("LlsReplicationUserAddExW"));
  81. pLlsCapabilityIsSupported = (PLLS_CAPABILITY_IS_SUPPORTED) GetProcAddress(LlsRPCHandle, ("LlsCapabilityIsSupported"));
  82. pLlsConnectW = (PLLS_CONNECT_W) GetProcAddress(LlsRPCHandle, ("LlsConnectW"));
  83. pLlsClose = (PLLS_CLOSE) GetProcAddress(LlsRPCHandle, ("LlsClose"));
  84. pLlsLicenseAddW = (PLLS_LICENSE_ADD_W) GetProcAddress(LlsRPCHandle, ("LlsLicenseAddW"));
  85. if ((pLlsReplConnect == NULL)
  86. || (pLlsReplClose == NULL)
  87. || (pLlsFreeMemory == NULL)
  88. || (pLlsReplicationRequestW == NULL)
  89. || (pLlsReplicationServerAddW == NULL)
  90. || (pLlsReplicationServerServiceAddW == NULL)
  91. || (pLlsReplicationServiceAddW == NULL)
  92. || (pLlsReplicationUserAddW == NULL)
  93. || (pLlsReplicationCertDbAddW == NULL)
  94. || (pLlsReplicationProductSecurityAddW == NULL)
  95. || (pLlsReplicationUserAddExW == NULL)
  96. || (pLlsCapabilityIsSupported == NULL)
  97. || (pLlsConnectW == NULL)
  98. || (pLlsClose == NULL)
  99. || (pLlsLicenseAddW == NULL))
  100. {
  101. Status = STATUS_INTERNAL_ERROR;
  102. }
  103. }
  104. else
  105. {
  106. Status = GetLastError();
  107. }
  108. }
  109. RtlLeaveCriticalSection(&g_csLock);
  110. return Status;
  111. }
  112. /////////////////////////////////////////////////////////////////////////
  113. NTSTATUS
  114. ReplicationInit ( )
  115. /*++
  116. Routine Description:
  117. Arguments:
  118. Return Value:
  119. --*/
  120. {
  121. DWORD Ignore;
  122. HANDLE Thread;
  123. NTSTATUS Status;
  124. #if DBG
  125. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_REPLICATION))
  126. dprintf(TEXT("LLS TRACE: ReplicationInit\n"));
  127. #endif
  128. //
  129. // Create the Replication Management event
  130. //
  131. Status = NtCreateEvent(
  132. &ReplicationEvent,
  133. EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE,
  134. NULL,
  135. SynchronizationEvent,
  136. FALSE
  137. );
  138. ASSERT(NT_SUCCESS(Status));
  139. //
  140. // Fire off the thread to watch for replication.
  141. //
  142. Thread = CreateThread(
  143. NULL,
  144. 0L,
  145. (LPTHREAD_START_ROUTINE) ReplicationManager,
  146. 0L,
  147. 0L,
  148. &Ignore
  149. );
  150. if (NULL != Thread)
  151. CloseHandle(Thread);
  152. return STATUS_SUCCESS;
  153. } // ReplicationInit
  154. /////////////////////////////////////////////////////////////////////////
  155. NTSTATUS
  156. ReplicationDo (
  157. LLS_HANDLE LlsHandle,
  158. LLS_REPL_HANDLE ReplHandle,
  159. DWORD LastReplicated
  160. )
  161. /*++
  162. Routine Description:
  163. Arguments:
  164. Return Value:
  165. --*/
  166. {
  167. NTSTATUS Status;
  168. PREPL_SERVICE_RECORD Services = NULL;
  169. ULONG ServicesTotalRecords = 0;
  170. PREPL_SERVER_RECORD Servers = NULL;
  171. ULONG ServersTotalRecords = 0;
  172. PREPL_SERVER_SERVICE_RECORD ServerServices = NULL;
  173. ULONG ServerServicesTotalRecords = 0;
  174. REPL_CERTIFICATE_DB_0 CertificateDB;
  175. REPL_PRODUCT_SECURITY_0 ProductSecurity;
  176. DWORD UserLevel = 0;
  177. REPL_USER_RECORD_CONTAINER UserDB;
  178. #if DBG
  179. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_REPLICATION))
  180. dprintf(TEXT("LLS TRACE: ReplicationDo\n"));
  181. #endif
  182. //
  183. // Pack all of our data into linear / self-relative buffers so we
  184. // can send them over.
  185. //
  186. ZeroMemory( &UserDB, sizeof( UserDB ) );
  187. ZeroMemory( &CertificateDB, sizeof( CertificateDB ) );
  188. ZeroMemory( &ProductSecurity, sizeof( ProductSecurity ) );
  189. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_USERS_EX ) )
  190. {
  191. UserLevel = 1;
  192. Status = PackAll( LastReplicated, &ServicesTotalRecords, &Services, &ServersTotalRecords, &Servers, &ServerServicesTotalRecords, &ServerServices, 1, &UserDB.Level1.NumUsers, &UserDB.Level1.Users );
  193. if (Status != STATUS_SUCCESS)
  194. goto ReplicationDoExit;
  195. }
  196. else
  197. {
  198. UserLevel = 0;
  199. Status = PackAll( LastReplicated, &ServicesTotalRecords, &Services, &ServersTotalRecords, &Servers, &ServerServicesTotalRecords, &ServerServices, 0, &UserDB.Level0.NumUsers, &UserDB.Level0.Users );
  200. if (Status != STATUS_SUCCESS)
  201. goto ReplicationDoExit;
  202. }
  203. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_CERT_DB ) )
  204. {
  205. Status = CertDbPack( &CertificateDB.StringSize, &CertificateDB.Strings, &CertificateDB.HeaderContainer.Level0.NumHeaders, &CertificateDB.HeaderContainer.Level0.Headers, &CertificateDB.ClaimContainer.Level0.NumClaims, &CertificateDB.ClaimContainer.Level0.Claims );
  206. if (Status != STATUS_SUCCESS)
  207. goto ReplicationDoExit;
  208. }
  209. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_PRODUCT_SECURITY ) )
  210. {
  211. Status = ProductSecurityPack( &ProductSecurity.StringSize, &ProductSecurity.Strings );
  212. if (Status != STATUS_SUCCESS)
  213. goto ReplicationDoExit;
  214. }
  215. //
  216. // Transmit...
  217. //
  218. Status = (*pLlsReplicationServiceAddW) ( ReplHandle, ServicesTotalRecords, Services );
  219. if (Status != STATUS_SUCCESS)
  220. goto ReplicationDoExit;
  221. Status = (*pLlsReplicationServerAddW) ( ReplHandle, ServersTotalRecords, Servers );
  222. if (Status != STATUS_SUCCESS)
  223. goto ReplicationDoExit;
  224. Status = (*pLlsReplicationServerServiceAddW) ( ReplHandle, ServerServicesTotalRecords, ServerServices );
  225. if (Status != STATUS_SUCCESS)
  226. goto ReplicationDoExit;
  227. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_USERS_EX ) )
  228. {
  229. Status = (*pLlsReplicationUserAddExW)( ReplHandle, UserLevel, &UserDB );
  230. if (Status != STATUS_SUCCESS)
  231. goto ReplicationDoExit;
  232. }
  233. else
  234. {
  235. Status = (*pLlsReplicationUserAddW) ( ReplHandle, UserDB.Level0.NumUsers, UserDB.Level0.Users );
  236. if (Status != STATUS_SUCCESS)
  237. goto ReplicationDoExit;
  238. }
  239. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_CERT_DB ) )
  240. {
  241. Status = (*pLlsReplicationCertDbAddW)( ReplHandle, 0, &CertificateDB );
  242. if (Status != STATUS_SUCCESS)
  243. goto ReplicationDoExit;
  244. }
  245. if ( (*pLlsCapabilityIsSupported)( LlsHandle, LLS_CAPABILITY_REPLICATE_PRODUCT_SECURITY ) )
  246. {
  247. Status = (*pLlsReplicationProductSecurityAddW)( ReplHandle, 0, &ProductSecurity );
  248. }
  249. ReplicationDoExit:
  250. if (Status != STATUS_SUCCESS) {
  251. #if DBG
  252. dprintf(TEXT("LLS Replication ABORT: 0x%lX\n"), Status);
  253. #endif
  254. }
  255. if (Services != NULL)
  256. MIDL_user_free(Services);
  257. if (Servers != NULL)
  258. MIDL_user_free(Servers);
  259. if ( 0 == UserLevel )
  260. {
  261. if (UserDB.Level0.Users != NULL)
  262. MIDL_user_free(UserDB.Level0.Users);
  263. }
  264. else
  265. {
  266. if (UserDB.Level1.Users != NULL)
  267. MIDL_user_free(UserDB.Level1.Users);
  268. }
  269. if (CertificateDB.Strings != NULL)
  270. MIDL_user_free(CertificateDB.Strings);
  271. if (CertificateDB.HeaderContainer.Level0.Headers != NULL)
  272. MIDL_user_free(CertificateDB.HeaderContainer.Level0.Headers);
  273. if (CertificateDB.ClaimContainer.Level0.Claims != NULL)
  274. MIDL_user_free(CertificateDB.ClaimContainer.Level0.Claims);
  275. if (ProductSecurity.Strings != NULL)
  276. MIDL_user_free(ProductSecurity.Strings);
  277. #if DBG
  278. if (TraceFlags & TRACE_REPLICATION)
  279. dprintf(TEXT(" LLS Replication Finished\n"));
  280. #endif
  281. return Status;
  282. } // ReplicationDo
  283. /////////////////////////////////////////////////////////////////////////
  284. VOID
  285. ReplicationManager (
  286. IN PVOID ThreadParameter
  287. )
  288. /*++
  289. Routine Description:
  290. Arguments:
  291. ThreadParameter - Not used.
  292. Return Value:
  293. This thread never exits.
  294. --*/
  295. {
  296. NTSTATUS Status;
  297. LLS_REPL_HANDLE ReplHandle = NULL;
  298. LLS_HANDLE LlsHandle = NULL;
  299. PREPL_REQUEST pReplInfo;
  300. TCHAR ReplicateTo[MAX_PATH + 1];
  301. DWORD LastReplicated;
  302. LPTSTR pReplicateTo = ReplicateTo;
  303. TCHAR LastFailedConnectionDownlevelReplicateTo[MAX_PATH + 1] = TEXT("");
  304. BOOL Replicate;
  305. HRESULT hr;
  306. UNREFERENCED_PARAMETER(ThreadParameter);
  307. #if DBG
  308. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_REPLICATION))
  309. dprintf(TEXT("LLS TRACE: ReplicationManager\n"));
  310. #endif
  311. //
  312. // Loop forever waiting to be given the opportunity to serve the
  313. // greater good.
  314. //
  315. for ( ; ; ) {
  316. //
  317. // Wait to be notified that there is work to be done
  318. //
  319. Status = NtWaitForSingleObject( ReplicationEvent, TRUE, NULL );
  320. #if DELAY_INITIALIZATION
  321. EnsureInitialized();
  322. #endif
  323. // Delayed LoadLibrary
  324. Status = ReplicationInitDelayed();
  325. if (NOERROR != Status)
  326. {
  327. //
  328. // Can't replicate
  329. //
  330. break;
  331. }
  332. // Update the replication-related ConfigInfo information.
  333. //
  334. ConfigInfoUpdate(NULL,TRUE);
  335. RtlEnterCriticalSection(&ConfigInfoLock);
  336. Replicate = ConfigInfo.Replicate;
  337. RtlLeaveCriticalSection(&ConfigInfoLock);
  338. if (Replicate) {
  339. //
  340. // So they said, go replicate my son... Yeah, but first we must ask
  341. // the master for permission.
  342. //
  343. //
  344. // Construct our repl record
  345. //
  346. pReplInfo = MIDL_user_allocate(sizeof(REPL_REQUEST));
  347. ASSERT(pReplInfo != NULL);
  348. if (pReplInfo != NULL) {
  349. ReplicateTo[0] = 0;
  350. pReplInfo->EnterpriseServer[0] = 0;
  351. RtlEnterCriticalSection(&ConfigInfoLock);
  352. if (ConfigInfo.ReplicateTo != NULL)
  353. {
  354. lstrcpyn(ReplicateTo,
  355. ConfigInfo.ReplicateTo,
  356. min(MAX_PATH, lstrlen(ConfigInfo.ReplicateTo) + 1));
  357. }
  358. if (ConfigInfo.EnterpriseServer != NULL)
  359. {
  360. hr = StringCbCopy(pReplInfo->EnterpriseServer, sizeof(pReplInfo->EnterpriseServer), ConfigInfo.EnterpriseServer);
  361. ASSERT(SUCCEEDED(hr));
  362. }
  363. pReplInfo->EnterpriseServerDate = ConfigInfo.EnterpriseServerDate;
  364. pReplInfo->LastReplicated = ConfigInfo.LastReplicatedSeconds;
  365. pReplInfo->CurrentTime = LastUsedTime;
  366. pReplInfo->NumberServices = 0;
  367. pReplInfo->NumberUsers = 0;
  368. pReplInfo->ReplSize = MAX_REPL_SIZE;
  369. pReplInfo->Backoff = 0;
  370. RtlLeaveCriticalSection(&ConfigInfoLock);
  371. #if DBG
  372. if (TraceFlags & TRACE_REPLICATION)
  373. dprintf(TEXT("LLS Starting Replication to: %s @ %s\n"),
  374. ReplicateTo, TimeToString(pReplInfo->CurrentTime));
  375. #endif
  376. Status = (*pLlsReplConnect) ( ReplicateTo,
  377. &ReplHandle );
  378. if ( STATUS_SUCCESS != Status ) {
  379. #if DBG
  380. dprintf(TEXT("LLS Error: LlsReplConnect failed: 0x%lX\n"),
  381. Status);
  382. #endif
  383. ReplHandle = NULL;
  384. }
  385. else {
  386. Status = (*pLlsConnectW)( ReplicateTo, &LlsHandle );
  387. if ( STATUS_SUCCESS != Status ) {
  388. #if DBG
  389. dprintf(TEXT("LLS Error: LlsConnectW failed: 0x%lX\n"),
  390. Status);
  391. #endif
  392. LlsHandle = NULL;
  393. }
  394. }
  395. if (Status != STATUS_SUCCESS) {
  396. DWORD dwWinError;
  397. DWORD dwBuildNumber;
  398. dwWinError = WinNtBuildNumberGet( ReplicateTo,
  399. &dwBuildNumber );
  400. if ( (ERROR_SUCCESS == dwWinError) &&
  401. (dwBuildNumber < 1057L) ) {
  402. // the ReplicateTo machine does not support the license
  403. // service
  404. if ( lstrcmpi(ReplicateTo,
  405. LastFailedConnectionDownlevelReplicateTo ) ) {
  406. hr = StringCbCopy(
  407. LastFailedConnectionDownlevelReplicateTo,
  408. sizeof(LastFailedConnectionDownlevelReplicateTo),
  409. ReplicateTo );
  410. ASSERT(SUCCEEDED(hr));
  411. LogEvent( LLS_EVENT_REPL_DOWNLEVEL_TARGET,
  412. 1,
  413. &pReplicateTo,
  414. Status );
  415. }
  416. }
  417. else {
  418. // the ReplicateTo machine should be running the license
  419. // service
  420. *LastFailedConnectionDownlevelReplicateTo = TEXT( '\0' );
  421. ThrottleLogEvent( LLS_EVENT_REPL_NO_CONNECTION,
  422. 1,
  423. &pReplicateTo,
  424. Status );
  425. }
  426. }
  427. else {
  428. *LastFailedConnectionDownlevelReplicateTo = TEXT( '\0' );
  429. Status = (*pLlsReplicationRequestW) ( ReplHandle,
  430. REPL_VERSION,
  431. pReplInfo );
  432. if (Status != STATUS_SUCCESS) {
  433. LogEvent( LLS_EVENT_REPL_REQUEST_FAILED,
  434. 1,
  435. &pReplicateTo,
  436. Status );
  437. }
  438. else {
  439. RtlEnterCriticalSection(&ConfigInfoLock);
  440. #ifdef DISABLED_FOR_NT5
  441. //swi, code review, ConfigInfo.EnterpriseServer is hard code allocated from heap for sizeof MAX_COMPUTERNAME_LENGTH+3 chars. This seems a strange allocation. It should dynamically changed whenever it needs to be refilled.
  442. hr = StringCchCopy(ConfigInfo.EnterpriseServer,
  443. MAX_COMPUTERNAME_LENGTH+3,
  444. pReplInfo->EnterpriseServer);
  445. ASSERT(SUCCEEDED(hr));
  446. #endif // DISABLED_FOR_NT5
  447. ConfigInfo.EnterpriseServerDate =
  448. pReplInfo->EnterpriseServerDate;
  449. ConfigInfo.IsReplicating = TRUE;
  450. LastReplicated = pReplInfo->LastReplicated;
  451. //
  452. // And lo, thou may proceed...
  453. //
  454. if (pReplInfo->Backoff == 0) {
  455. if ( ConfigInfo.LogLevel ) {
  456. LogEvent( LLS_EVENT_REPL_START,
  457. 1,
  458. &pReplicateTo,
  459. ERROR_SUCCESS );
  460. }
  461. Status = ReplicationDo( LlsHandle,
  462. ReplHandle,
  463. LastReplicated );
  464. if ( STATUS_SUCCESS != Status ) {
  465. LogEvent( LLS_EVENT_REPL_FAILED,
  466. 1,
  467. &pReplicateTo,
  468. Status );
  469. }
  470. else if ( ConfigInfo.LogLevel ) {
  471. LogEvent( LLS_EVENT_REPL_END,
  472. 1,
  473. &pReplicateTo,
  474. ERROR_SUCCESS );
  475. }
  476. //
  477. // Need to update when next we should replicate
  478. //
  479. ConfigInfo.LastReplicatedSeconds = DateSystemGet();
  480. GetLocalTime(&ConfigInfo.LastReplicated);
  481. ReplicationTimeSet();
  482. }
  483. else {
  484. LogEvent( LLS_EVENT_REPL_BACKOFF,
  485. 1,
  486. &pReplicateTo,
  487. ERROR_SUCCESS );
  488. }
  489. ConfigInfo.IsReplicating = FALSE;
  490. RtlLeaveCriticalSection(&ConfigInfoLock);
  491. }
  492. }
  493. //
  494. // Disconnect from Master Server
  495. //
  496. if ( NULL != LlsHandle ) {
  497. (*pLlsClose)( LlsHandle );
  498. LlsHandle = NULL;
  499. }
  500. if ( NULL != ReplHandle ) {
  501. Status = (*pLlsReplClose) ( &ReplHandle );
  502. if ((STATUS_SUCCESS != Status) && (NULL != ReplHandle))
  503. {
  504. RpcSmDestroyClientContext( &ReplHandle );
  505. ReplHandle = NULL;
  506. }
  507. }
  508. MIDL_user_free( pReplInfo );
  509. }
  510. }
  511. }
  512. } // ReplicationManager
  513. /////////////////////////////////////////////////////////////////////////
  514. VOID
  515. ReplicationTimeSet ( )
  516. /*++
  517. Routine Description:
  518. Arguments:
  519. Return Value:
  520. --*/
  521. {
  522. DWORD CurrTime, ReplTime, Time;
  523. #if DBG
  524. if (TraceFlags & (TRACE_FUNCTION_TRACE | TRACE_REPLICATION))
  525. dprintf(TEXT("LLS TRACE: ReplicationTimeSet\n"));
  526. #endif
  527. ReplTime = Time = 0;
  528. //
  529. // Figure out what new time to set it to
  530. //
  531. if (!ConfigInfo.Replicate)
  532. return;
  533. //
  534. // If REPLICATE_DELTA it is easy as we just take the delta and apply it to
  535. // the last replication time. Otherwise we have to convert the time from
  536. // midnight.
  537. //
  538. //
  539. // Figure out how long since we last replicated
  540. //
  541. ReplTime = ConfigInfo.ReplicationTime;
  542. if (ConfigInfo.ReplicationType == REPLICATE_DELTA) {
  543. Time = DateSystemGet() - ConfigInfo.LastReplicatedSeconds;
  544. //
  545. // If we have already gone past when we should replicate then schedule
  546. // one real soon now (10 minutes).
  547. //
  548. if (Time > ReplTime)
  549. Time = 10 * 60;
  550. else
  551. Time = ReplTime - Time;
  552. Time += DateLocalGet();
  553. } else {
  554. //
  555. // Need to adjust time to midnight - do this by MOD of seconds
  556. // per day.
  557. //
  558. CurrTime = DateLocalGet();
  559. Time = CurrTime - ((CurrTime / (60 * 60 * 24)) * (60 * 60 * 24));
  560. CurrTime = CurrTime - Time;
  561. //
  562. // Time = seconds past midnight.
  563. // CurrTime = Todays @ 12:00 AM
  564. // Figure out if we are past the replication time, if so schedule it
  565. // for tomorrow, else today.
  566. //
  567. if (Time > ReplTime)
  568. Time = CurrTime + (60 * 60 * 24) + ReplTime;
  569. else
  570. Time = CurrTime + ReplTime;
  571. }
  572. ConfigInfo.NextReplication = Time;
  573. } // ReplicationTimeSet