Source code of Windows XP (NT5)
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.

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