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.

1124 lines
29 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1998 - 2001
  4. Module Name:
  5. time.c
  6. Abstract:
  7. Handles the various functions for the time functionality of netdom
  8. --*/
  9. #include "pch.h"
  10. #pragma hdrstop
  11. #include <netdom.h>
  12. DWORD
  13. NetDompTimeGetDc(
  14. IN PWSTR Domain,
  15. IN PWSTR DestServer,
  16. IN PND5_AUTH_INFO AuthInfo,
  17. OUT PWSTR *Dc
  18. )
  19. /*++
  20. Routine Description:
  21. This function will find the DC to use as a time source for the given machine
  22. Arguments:
  23. Domain - Domain to get a time source from
  24. DestServer - Server for which we need a time source
  25. AuthInfo - Auth info to connect to the destination server for
  26. Dc - Where the dc name is returned. Freed via NetApiBufferFree
  27. Return Value:
  28. ERROR_INVALID_PARAMETER - No object name was supplied
  29. --*/
  30. {
  31. DWORD Win32Err = ERROR_SUCCESS;
  32. PDOMAIN_CONTROLLER_INFO DcInfo = NULL;
  33. BOOL Retry = FALSE;
  34. WCHAR FlatName[ CNLEN + 1 ];
  35. ULONG Len = CNLEN + 1;
  36. //
  37. // Get a server name
  38. //
  39. Win32Err = DsGetDcName( NULL,
  40. Domain,
  41. NULL,
  42. NULL,
  43. DS_GOOD_TIMESERV_PREFERRED,
  44. &DcInfo );
  45. //
  46. // If we have a destination server specified, make sure that we
  47. // aren't talking to ourselves... That would kind of defeat the purpose
  48. //
  49. if ( Win32Err == ERROR_SUCCESS && DestServer ) {
  50. if ( !_wcsicmp( DcInfo->DomainControllerName + 2, DestServer ) ) {
  51. Retry = TRUE;
  52. } else {
  53. //
  54. // Handle the case where we have a Dns dc name and a netbios server name
  55. //
  56. if ( wcslen( DestServer ) <= CNLEN && FLAG_ON( DcInfo->Flags, DS_IS_DNS_NAME ) ) {
  57. if ( !DnsHostnameToComputerName( DcInfo->DomainControllerName + 2,
  58. FlatName,
  59. &Len ) ) {
  60. Win32Err = GetLastError();
  61. } else {
  62. if ( !_wcsicmp( FlatName, DestServer ) ) {
  63. Retry = TRUE;
  64. }
  65. }
  66. }
  67. }
  68. }
  69. //
  70. // We have a dc name specified, so connect to that machine, and try it again, with
  71. // the AvoidSelf flag. If we can't (like this is an NT4 PDC) then return that we
  72. // can't find a dc
  73. //
  74. if ( Win32Err == ERROR_SUCCESS && Retry ) {
  75. NetApiBufferFree( DcInfo );
  76. DcInfo = NULL;
  77. Win32Err = NetpManageIPCConnect( DestServer,
  78. AuthInfo->User,
  79. AuthInfo->Password,
  80. NETSETUPP_CONNECT_IPC );
  81. if ( Win32Err == ERROR_SUCCESS ) {
  82. Win32Err = DsGetDcName( DestServer,
  83. Domain,
  84. NULL,
  85. NULL,
  86. DS_GOOD_TIMESERV_PREFERRED | DS_AVOID_SELF,
  87. &DcInfo );
  88. NetpManageIPCConnect( DestServer,
  89. AuthInfo->User,
  90. AuthInfo->Password,
  91. NETSETUPP_DISCONNECT_IPC );
  92. }
  93. }
  94. //
  95. // Copy the name if everything worked
  96. //
  97. if ( Win32Err == ERROR_SUCCESS ) {
  98. Win32Err = NetApiBufferAllocate( ( wcslen( DcInfo->DomainControllerName + 2 ) + 1 ) *
  99. sizeof( WCHAR ),
  100. (PVOID*)Dc );
  101. if ( Win32Err == ERROR_SUCCESS ) {
  102. wcscpy( *Dc, DcInfo->DomainControllerName + 2 );
  103. }
  104. }
  105. NetApiBufferFree( DcInfo );
  106. return( Win32Err );
  107. }
  108. DWORD
  109. NetDompEnableSystimePriv(
  110. VOID
  111. )
  112. /*++
  113. Routine Description:
  114. This function will enable the systemtime privilege for the current thread
  115. Arguments:
  116. VOID
  117. Return Value:
  118. ERROR_INVALID_PARAMETER - No object name was supplied
  119. --*/
  120. {
  121. NTSTATUS Status;
  122. HANDLE ThreadToken;
  123. TOKEN_PRIVILEGES Enabled, Previous;
  124. DWORD PreviousSize;
  125. Status = NtOpenThreadToken( NtCurrentThread(),
  126. TOKEN_READ | TOKEN_WRITE,
  127. TRUE,
  128. &ThreadToken );
  129. if ( Status == STATUS_NO_TOKEN ) {
  130. Status = NtOpenProcessToken( NtCurrentProcess(),
  131. TOKEN_WRITE | TOKEN_READ,
  132. &ThreadToken );
  133. }
  134. if ( NT_SUCCESS( Status ) ) {
  135. Enabled.PrivilegeCount = 1;
  136. Enabled.Privileges[0].Luid.LowPart = SE_SYSTEMTIME_PRIVILEGE;
  137. Enabled.Privileges[0].Luid.HighPart = 0;
  138. Enabled.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  139. PreviousSize = sizeof( Previous );
  140. Status = NtAdjustPrivilegesToken( ThreadToken,
  141. FALSE,
  142. &Enabled,
  143. sizeof( Enabled ),
  144. &Previous,
  145. &PreviousSize );
  146. }
  147. return( RtlNtStatusToDosError( Status ) );
  148. }
  149. DWORD
  150. NetDompGetTimeTripLength(
  151. IN PWSTR Server,
  152. IN OUT PDWORD TripLength
  153. )
  154. /*++
  155. Routine Description:
  156. This function will get an approximate elapsed time for getting the time from a domain
  157. controller
  158. Arguments:
  159. Server - Server to get the elapsed trip time for
  160. TripLength - Number of ticks it takes to get the time
  161. Return Value:
  162. ERROR_SUCCESS - The function succeeded
  163. --*/
  164. {
  165. DWORD Win32Err = ERROR_SUCCESS;
  166. ULONG StartTime, EndTime, ElapsedTime = 0, i;
  167. PTIME_OF_DAY_INFO TOD;
  168. #define NETDOMP_NUM_TRIPS 2
  169. //
  170. // Get the average from several time trips
  171. //
  172. for ( i = 0; i < NETDOMP_NUM_TRIPS && Win32Err == ERROR_SUCCESS; i++ ) {
  173. StartTime = GetTickCount();
  174. Win32Err = NetRemoteTOD( Server, ( LPBYTE * )&TOD );
  175. EndTime = GetTickCount();
  176. ElapsedTime += ( EndTime - StartTime );
  177. NetApiBufferFree( TOD );
  178. }
  179. if ( Win32Err == ERROR_SUCCESS ) {
  180. *TripLength = ElapsedTime / NETDOMP_NUM_TRIPS;
  181. }
  182. return( Win32Err );
  183. }
  184. DWORD
  185. NetDompResetSingleClient(
  186. IN PWSTR Server,
  187. IN PWSTR Dc,
  188. IN PND5_AUTH_INFO ObjectAuthInfo,
  189. IN DWORD DcDelay
  190. )
  191. /*++
  192. Routine Description:
  193. This function sync the time between and NT5 client and the specified domain controller
  194. Arguments:
  195. Server - Server to reset the time for
  196. Dc - Domain controller to sync the time against
  197. ObjectAuthInfo - User info to connect to the server as
  198. DcDelay - The amount of time it takes to talk to the dc
  199. Return Value:
  200. ERROR_SUCCESS - The function succeeded
  201. --*/
  202. {
  203. DWORD Win32Err = ERROR_SUCCESS;
  204. BOOL Connected = FALSE;
  205. //PSTR ServerA = NULL;
  206. //
  207. // Set up a connection to the client machine
  208. //
  209. Win32Err = NetpManageIPCConnect( Server,
  210. ObjectAuthInfo->User,
  211. ObjectAuthInfo->Password,
  212. NETSETUPP_CONNECT_IPC );
  213. if ( Win32Err == ERROR_SUCCESS ) {
  214. Connected = TRUE;
  215. } else {
  216. goto ResetSingleError;
  217. }
  218. //if ( Server ) {
  219. //
  220. // Win32Err = NetApiBufferAllocate( wcstombs( NULL, Server, wcslen( Server ) + 1 ) + 3,
  221. // &ServerA );
  222. // if ( Win32Err != ERROR_SUCCESS ) {
  223. //
  224. // goto ResetSingleError;
  225. // }
  226. //
  227. // if ( *Server == L'\\' ) {
  228. //
  229. // strcpy( ServerA, "\\\\" );
  230. // wcstombs( ServerA + 2, Server, wcslen( Server ) + 1 );
  231. //
  232. // } else {
  233. //
  234. // wcstombs( ServerA, Server, wcslen( Server ) + 1 );
  235. // }
  236. //}
  237. Win32Err = W32TimeSyncNow( Server,
  238. FALSE, // no wait
  239. TimeSyncFlag_HardResync );
  240. ResetSingleError:
  241. if ( Connected ) {
  242. NetpManageIPCConnect( Server,
  243. ObjectAuthInfo->User,
  244. ObjectAuthInfo->Password,
  245. NETSETUPP_DISCONNECT_IPC );
  246. }
  247. //NetApiBufferFree( ServerA );
  248. return( Win32Err );
  249. }
  250. DWORD
  251. NetDompVerifySingleClient(
  252. IN PWSTR Server,
  253. IN PWSTR Dc,
  254. IN PND5_AUTH_INFO ObjectAuthInfo,
  255. IN DWORD DcDelay,
  256. IN BOOL * InSync
  257. )
  258. /*++
  259. Routine Description:
  260. This function will verify that the time between the specified server and domain controller
  261. is within the acceptable skew
  262. Arguments:
  263. Server - Server to verify the time for
  264. Dc - Domain controller to verify the time against
  265. ObjectAuthInfo - User and password to connect to the client as
  266. DcDelay - How long does it take to get the time from the domain controller
  267. InSync - Where the results are returned.
  268. Return Value:
  269. ERROR_SUCCESS - The function succeeded
  270. --*/
  271. {
  272. DWORD Win32Err = ERROR_SUCCESS;
  273. SYSTEMTIME StartTime, EndTime;
  274. PTIME_OF_DAY_INFO DcTOD = NULL, ClientTOD = NULL;
  275. BOOL Connected = FALSE;
  276. FILETIME StartFile, EndFile;
  277. LARGE_INTEGER ElapsedTime, TimeDifference, DcTime, ClientTime, UpdatedDcTime, TimeSkew,
  278. AllowedSkew;
  279. TIME_FIELDS TimeFields;
  280. LARGE_INTEGER SystemTime;
  281. //
  282. // Set the allowable time skew. 600,000,000L is the number of 100 nanoseconds in a minute
  283. //
  284. #define NETDOMP_VERIFY_SKEW 0xB2D05E00
  285. //
  286. // Assume the clocks are fine
  287. //
  288. *InSync = TRUE;
  289. //
  290. // Set up a connection to the client machine
  291. //
  292. Win32Err = NetpManageIPCConnect( Server,
  293. ObjectAuthInfo->User,
  294. ObjectAuthInfo->Password,
  295. NETSETUPP_CONNECT_IPC );
  296. if ( Win32Err == ERROR_SUCCESS ) {
  297. Connected = TRUE;
  298. } else {
  299. goto VerifySingleError;
  300. }
  301. //
  302. // Ok, first, we get the time on the dc, then we get the time on the client, keeping in mind
  303. // how long that takes,
  304. //
  305. Win32Err = NetRemoteTOD( Dc, ( LPBYTE * )&DcTOD );
  306. if ( Win32Err == ERROR_SUCCESS ) {
  307. Win32Err = NetRemoteTOD( Server, ( LPBYTE * )&ClientTOD );
  308. }
  309. if ( Win32Err != ERROR_SUCCESS ) {
  310. goto VerifySingleError;
  311. }
  312. //
  313. // Ok, now we've gotten all the info we need, assemble it... Note that we are only computing
  314. // the difference in time here...
  315. //
  316. SystemTimeToFileTime( &StartTime, &StartFile );
  317. SystemTimeToFileTime( &EndTime, &EndFile );
  318. ElapsedTime = RtlLargeIntegerSubtract( *( PLARGE_INTEGER )&EndFile,
  319. *( PLARGE_INTEGER )&StartFile );
  320. TimeFields.Hour = ( WORD )DcTOD->tod_hours;
  321. TimeFields.Minute = ( WORD )DcTOD->tod_mins;
  322. TimeFields.Second = ( WORD )DcTOD->tod_secs;
  323. TimeFields.Milliseconds = ( WORD )DcTOD->tod_hunds * 10;
  324. TimeFields.Day = ( WORD )DcTOD->tod_day;
  325. TimeFields.Month = ( WORD )DcTOD->tod_month;
  326. TimeFields.Year = ( WORD )DcTOD->tod_year;
  327. if ( !RtlTimeFieldsToTime( &TimeFields, &DcTime ) ) {
  328. Win32Err = ERROR_INVALID_PARAMETER;
  329. }
  330. TimeFields.Hour = ( WORD )ClientTOD->tod_hours;
  331. TimeFields.Minute = ( WORD )ClientTOD->tod_mins;
  332. TimeFields.Second = ( WORD )ClientTOD->tod_secs;
  333. TimeFields.Milliseconds = ( WORD )ClientTOD->tod_hunds * 10;
  334. TimeFields.Day = ( WORD )ClientTOD->tod_day;
  335. TimeFields.Month = ( WORD )ClientTOD->tod_month;
  336. TimeFields.Year = ( WORD )ClientTOD->tod_year;
  337. if ( !RtlTimeFieldsToTime( &TimeFields, &ClientTime ) ) {
  338. Win32Err = ERROR_INVALID_PARAMETER;
  339. }
  340. //
  341. // Add the time it takes to get the time from the dc.
  342. //
  343. UpdatedDcTime = RtlLargeIntegerAdd( DcTime, ElapsedTime );
  344. //
  345. // Compute the difference in time
  346. //
  347. if ( RtlLargeIntegerGreaterThan( UpdatedDcTime, ClientTime ) ) {
  348. TimeSkew = RtlLargeIntegerSubtract( UpdatedDcTime,
  349. ClientTime );
  350. } else {
  351. TimeSkew = RtlLargeIntegerSubtract( ClientTime,
  352. UpdatedDcTime );
  353. }
  354. //
  355. // Now, see if there is a time difference greater than the allowable skew
  356. //
  357. AllowedSkew = RtlConvertUlongToLargeInteger( NETDOMP_VERIFY_SKEW );
  358. if ( RtlLargeIntegerGreaterThan( TimeSkew, AllowedSkew ) ) {
  359. *InSync = FALSE;
  360. }
  361. VerifySingleError:
  362. if ( Connected ) {
  363. NetpManageIPCConnect( Server,
  364. ObjectAuthInfo->User,
  365. ObjectAuthInfo->Password,
  366. NETSETUPP_DISCONNECT_IPC );
  367. }
  368. NetApiBufferFree( ClientTOD );
  369. NetApiBufferFree( DcTOD );
  370. return( Win32Err );
  371. }
  372. VOID
  373. NetDompDisplayTimeVerify(
  374. IN PWSTR Server,
  375. IN DWORD Results,
  376. IN BOOL InSync
  377. )
  378. /*++
  379. Routine Description:
  380. This function will display the results of the time verification
  381. Arguments:
  382. Server - Server which had the time verified
  383. Results - The error code of the verification attempt
  384. InSync - Whether the clocks are within the skew. Only valid if Results is ERROR_SUCCESS
  385. Return Value:
  386. VOID
  387. --*/
  388. {
  389. NetDompDisplayMessage( MSG_TIME_COMPUTER, Server );
  390. if ( Results != ERROR_SUCCESS ) {
  391. NetDompDisplayErrorMessage( Results );
  392. } else {
  393. NetDompDisplayMessage( InSync ? MSG_TIME_SUCCESS : MSG_TIME_FAILURE );
  394. }
  395. }
  396. DWORD
  397. NetDompVerifyTime(
  398. IN PWSTR Domain,
  399. IN PWSTR Server, OPTIONAL
  400. IN PND5_AUTH_INFO DomainAuthInfo,
  401. IN PND5_AUTH_INFO ObjectAuthInfo,
  402. IN PWSTR Dc,
  403. IN BOOL AllWorkstation,
  404. IN BOOL AllServer
  405. )
  406. /*++
  407. Routine Description:
  408. This function will verify the time between some or all of the servers/workstations in a
  409. domain against the specified domain controller
  410. Arguments:
  411. Domain - Domain containing the servers/workstations
  412. Server - Name of a specific machine to verify the time for
  413. DomainAuthInfo - User and password for the domain controller
  414. ObjectAuthInfo - User and password for the servers/workstations
  415. Dc - Name of a domain controller in the domain to use as a time source
  416. AllWorkstation - If TRUE, verify the time for all the workstations
  417. AllServer - If TRUE, verify the time for all the servers
  418. Return Value:
  419. ERROR_SUCCESS - The function succeeded
  420. ERROR_INVALID_PARAMETER - No server, workstation or machine was specified
  421. --*/
  422. {
  423. DWORD Win32Err = ERROR_SUCCESS, Err2;
  424. BOOL DcSession = FALSE, InSync;
  425. DWORD DcDelay;
  426. LPUSER_INFO_0 UserList = NULL;
  427. PWSTR FullDc = NULL, Lop;
  428. ULONG ResumeHandle = 0, Count = 0, TotalCount = 0, i, j;
  429. ULONG Types[] = {
  430. FILTER_WORKSTATION_TRUST_ACCOUNT,
  431. FILTER_SERVER_TRUST_ACCOUNT
  432. };
  433. BOOL ProcessType[ sizeof( Types ) / sizeof( ULONG ) ];
  434. ProcessType[ 0 ] = AllWorkstation;
  435. ProcessType[ 1 ] = AllServer;
  436. //
  437. // Make sure that there is something to do
  438. //
  439. if ( !Server && !AllWorkstation && !AllServer ) {
  440. return( ERROR_INVALID_PARAMETER );
  441. }
  442. //
  443. // Build a full machine name
  444. //
  445. if ( Dc && *Dc != L'\\' ) {
  446. Win32Err = NetApiBufferAllocate( ( wcslen( Dc ) + 3 ) * sizeof( WCHAR ),
  447. ( PVOID * )&FullDc );
  448. if ( Win32Err == ERROR_SUCCESS ) {
  449. swprintf( FullDc, L"\\\\%ws", Dc );
  450. }
  451. } else {
  452. FullDc = Dc;
  453. }
  454. //
  455. // Set up a session
  456. //
  457. Win32Err = NetpManageIPCConnect( FullDc,
  458. DomainAuthInfo->User,
  459. DomainAuthInfo->Password,
  460. NETSETUPP_CONNECT_IPC );
  461. if ( Win32Err == ERROR_SUCCESS ) {
  462. DcSession = FALSE;
  463. }
  464. //
  465. // See how long it takes to get to the dc
  466. //
  467. if ( Win32Err == ERROR_SUCCESS ) {
  468. Win32Err = NetDompGetTimeTripLength( Dc,
  469. &DcDelay );
  470. }
  471. if ( Win32Err != ERROR_SUCCESS ) {
  472. goto VerifyTimeError;
  473. }
  474. NetDompDisplayMessage( MSG_TIME_VERIFY );
  475. //
  476. // Verify a single machine
  477. //
  478. if ( Server ) {
  479. Win32Err = NetDompVerifySingleClient( Server,
  480. Dc,
  481. ObjectAuthInfo,
  482. DcDelay,
  483. &InSync );
  484. NetDompDisplayTimeVerify( Server,
  485. Win32Err,
  486. InSync );
  487. }
  488. //
  489. // Verify all the workstations/servers, if requested.
  490. //
  491. for ( i = 0; i < sizeof( Types ) / sizeof( ULONG ); i++ ) {
  492. if ( !ProcessType[ i ] ) {
  493. continue;
  494. }
  495. do {
  496. Win32Err = NetUserEnum( FullDc,
  497. 0,
  498. Types[ i ],
  499. ( LPBYTE * )&UserList,
  500. MAX_PREFERRED_LENGTH,
  501. &Count,
  502. &TotalCount,
  503. &ResumeHandle );
  504. if ( Win32Err == ERROR_SUCCESS || Win32Err == ERROR_MORE_DATA ) {
  505. for ( j = 0; j < Count; j++ ) {
  506. Lop = wcsrchr( UserList[ j ].usri0_name, L'$' );
  507. if ( Lop ) {
  508. *Lop = UNICODE_NULL;
  509. }
  510. Err2 = NetDompVerifySingleClient( UserList[ j ].usri0_name,
  511. Dc,
  512. ObjectAuthInfo,
  513. DcDelay,
  514. &InSync );
  515. NetDompDisplayTimeVerify( UserList[ j ].usri0_name,
  516. Err2,
  517. InSync );
  518. }
  519. NetApiBufferFree( UserList );
  520. }
  521. } while ( Win32Err == ERROR_MORE_DATA );
  522. }
  523. VerifyTimeError:
  524. if ( DcSession ) {
  525. NetpManageIPCConnect( FullDc,
  526. DomainAuthInfo->User,
  527. DomainAuthInfo->Password,
  528. NETSETUPP_DISCONNECT_IPC );
  529. }
  530. if ( FullDc != Dc ) {
  531. NetApiBufferFree( FullDc );
  532. }
  533. return( Win32Err );
  534. }
  535. DWORD
  536. NetDompResetTime(
  537. IN PWSTR Domain,
  538. IN PWSTR Server, OPTIONAL
  539. IN PND5_AUTH_INFO DomainAuthInfo,
  540. IN PND5_AUTH_INFO ObjectAuthInfo,
  541. IN PWSTR Dc,
  542. IN BOOL AllWorkstation,
  543. IN BOOL AllServer
  544. )
  545. /*++
  546. Routine Description:
  547. This function will reset the time between some or all of the servers/workstations in a
  548. domain against the specified domain controller
  549. Arguments:
  550. Domain - Domain containing the servers/workstations
  551. Server - Name of a specific machine to reset the time for
  552. DomainAuthInfo - User and password for the domain controller
  553. ObjectAuthInfo - User and password for the servers/workstations
  554. Dc - Name of a domain controller in the domain to use as a time source
  555. AllWorkstation - If TRUE, reset the time for all the workstations
  556. AllServer - If TRUE, reset the time for all the servers
  557. Return Value:
  558. ERROR_SUCCESS - The function succeeded
  559. ERROR_INVALID_PARAMETER - No server, workstation or machine was specified
  560. --*/
  561. {
  562. DWORD Win32Err = ERROR_SUCCESS, Err2;
  563. BOOL DcSession = FALSE, InSync;
  564. DWORD DcDelay;
  565. LPUSER_INFO_0 UserList = NULL;
  566. PWSTR FullDc = NULL, Lop;
  567. ULONG ResumeHandle = 0, Count = 0, TotalCount = 0, i, j;
  568. ULONG Types[] = {
  569. FILTER_WORKSTATION_TRUST_ACCOUNT,
  570. FILTER_SERVER_TRUST_ACCOUNT
  571. };
  572. BOOL ProcessType[ sizeof( Types ) / sizeof( ULONG ) ];
  573. ProcessType[ 0 ] = AllWorkstation;
  574. ProcessType[ 1 ] = AllServer;
  575. //
  576. // Make sure that there is something to do
  577. //
  578. if ( !Server && !AllWorkstation && !AllServer ) {
  579. return( ERROR_INVALID_PARAMETER );
  580. }
  581. if ( Dc && *Dc != L'\\' ) {
  582. Win32Err = NetApiBufferAllocate( ( wcslen( Dc ) + 3 ) * sizeof( WCHAR ),
  583. ( PVOID * )&FullDc );
  584. if ( Win32Err == ERROR_SUCCESS ) {
  585. swprintf( FullDc, L"\\\\%ws", Dc );
  586. }
  587. } else {
  588. FullDc = Dc;
  589. }
  590. Win32Err = NetpManageIPCConnect( FullDc,
  591. DomainAuthInfo->User,
  592. DomainAuthInfo->Password,
  593. NETSETUPP_CONNECT_IPC );
  594. if ( Win32Err == ERROR_SUCCESS ) {
  595. DcSession = FALSE;
  596. }
  597. //
  598. // Get the trip time to the dc
  599. //
  600. if ( Win32Err == ERROR_SUCCESS ) {
  601. Win32Err = NetDompGetTimeTripLength( Dc,
  602. &DcDelay );
  603. }
  604. if ( Win32Err != ERROR_SUCCESS ) {
  605. goto ResetTimeError;
  606. }
  607. NetDompDisplayMessage( MSG_TIME_VERIFY );
  608. //
  609. // Reset the client, if needed
  610. //
  611. if ( Server ) {
  612. Win32Err = NetDompVerifySingleClient( Server,
  613. Dc,
  614. ObjectAuthInfo,
  615. DcDelay,
  616. &InSync );
  617. if ( Win32Err == ERROR_SUCCESS && !InSync ) {
  618. Win32Err = NetDompResetSingleClient( Server,
  619. Dc,
  620. ObjectAuthInfo,
  621. DcDelay );
  622. }
  623. }
  624. //
  625. // Do all the workstations/servers, if required
  626. //
  627. for ( i = 0; i < sizeof( Types ) / sizeof( ULONG ); i++ ) {
  628. if ( !ProcessType[ i ] ) {
  629. continue;
  630. }
  631. do {
  632. Win32Err = NetUserEnum( FullDc,
  633. 0,
  634. Types[ i ],
  635. ( LPBYTE * )&UserList,
  636. MAX_PREFERRED_LENGTH,
  637. &Count,
  638. &TotalCount,
  639. &ResumeHandle );
  640. if ( Win32Err == ERROR_SUCCESS || Win32Err == ERROR_MORE_DATA ) {
  641. for ( j = 0; j < Count; j++ ) {
  642. Lop = wcsrchr( UserList[ j ].usri0_name, L'$' );
  643. if ( Lop ) {
  644. *Lop = UNICODE_NULL;
  645. }
  646. Err2 = NetDompVerifySingleClient( UserList[ j ].usri0_name,
  647. Dc,
  648. ObjectAuthInfo,
  649. DcDelay,
  650. &InSync );
  651. if ( Err2 == ERROR_SUCCESS && !InSync ) {
  652. Err2 = NetDompResetSingleClient( UserList[ j ].usri0_name,
  653. Dc,
  654. ObjectAuthInfo,
  655. DcDelay );
  656. }
  657. }
  658. NetApiBufferFree( UserList );
  659. }
  660. } while ( Win32Err == ERROR_MORE_DATA );
  661. }
  662. ResetTimeError:
  663. if ( DcSession ) {
  664. NetpManageIPCConnect( FullDc,
  665. DomainAuthInfo->User,
  666. DomainAuthInfo->Password,
  667. NETSETUPP_DISCONNECT_IPC );
  668. }
  669. if ( FullDc != Dc ) {
  670. NetApiBufferFree( FullDc );
  671. }
  672. return( Win32Err );
  673. }
  674. DWORD
  675. NetDompHandleTime(ARG_RECORD * rgNetDomArgs)
  676. /*++
  677. Routine Description:
  678. This function will handle the NETDOM TIME requirements
  679. Arguments:
  680. Args - List of command line arguments
  681. Return Value:
  682. ERROR_INVALID_PARAMETER - No object name was supplied
  683. --*/
  684. {
  685. DWORD Win32Err = ERROR_SUCCESS;
  686. PWSTR Domain = NULL, Dc = NULL;
  687. ND5_AUTH_INFO DomainUser, ObjectUser;
  688. ULONG i;
  689. PWSTR Object = rgNetDomArgs[eObject].strValue;
  690. if (!Object)
  691. {
  692. DisplayHelp(ePriTime);
  693. return( ERROR_INVALID_PARAMETER );
  694. }
  695. RtlZeroMemory( &DomainUser, sizeof( ND5_AUTH_INFO ) );
  696. RtlZeroMemory( &ObjectUser, sizeof( ND5_AUTH_INFO ) );
  697. //
  698. // Validate the args
  699. //
  700. Win32Err = NetDompValidateSecondaryArguments(rgNetDomArgs,
  701. eObject,
  702. eCommDomain,
  703. eCommUserNameO,
  704. eCommPasswordO,
  705. eCommUserNameD,
  706. eCommPasswordD,
  707. eQueryServer,
  708. eQueryWksta,
  709. eCommVerify,
  710. eCommReset,
  711. eCommVerbose,
  712. eArgEnd);
  713. if ( Win32Err != ERROR_SUCCESS ) {
  714. DisplayHelp(ePriTime);
  715. goto HandleTimeExit;
  716. }
  717. //
  718. // Verify that we don't have too many arguments
  719. //
  720. if ( CmdFlagOn(rgNetDomArgs, eCommVerify) &&
  721. CmdFlagOn(rgNetDomArgs, eCommReset) ) {
  722. NetDompDisplayUnexpectedParameter(rgNetDomArgs[eCommReset].strArg1);
  723. Win32Err = ERROR_INVALID_PARAMETER;
  724. goto HandleTimeExit;
  725. }
  726. //
  727. // Ok, make sure that we have a specified domain...
  728. //
  729. Win32Err = NetDompGetDomainForOperation(rgNetDomArgs,
  730. Object,
  731. TRUE,
  732. &Domain);
  733. if ( Win32Err != ERROR_SUCCESS ) {
  734. goto HandleTimeExit;
  735. }
  736. //
  737. // Get the password and user if it exists
  738. //
  739. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameD) ) {
  740. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  741. eCommUserNameD,
  742. Domain,
  743. &DomainUser);
  744. if ( Win32Err != ERROR_SUCCESS ) {
  745. goto HandleTimeExit;
  746. }
  747. }
  748. if ( CmdFlagOn(rgNetDomArgs, eCommUserNameO) ) {
  749. Win32Err = NetDompGetUserAndPasswordForOperation(rgNetDomArgs,
  750. eCommUserNameO,
  751. Object,
  752. &ObjectUser );
  753. if ( Win32Err != ERROR_SUCCESS ) {
  754. goto HandleTimeExit;
  755. }
  756. }
  757. //
  758. // Get the name of a domain controller
  759. //
  760. Win32Err = NetDompTimeGetDc( Domain,
  761. Object,
  762. &ObjectUser,
  763. &Dc );
  764. if ( Win32Err != ERROR_SUCCESS ) {
  765. goto HandleTimeExit;
  766. }
  767. //
  768. // Now, see what we are supposed to do
  769. //
  770. if ( CmdFlagOn(rgNetDomArgs, eCommVerify) ) {
  771. Win32Err = NetDompVerifyTime( Domain,
  772. Object,
  773. &DomainUser,
  774. &ObjectUser,
  775. Dc,
  776. CmdFlagOn(rgNetDomArgs, eQueryWksta),
  777. CmdFlagOn(rgNetDomArgs, eQueryServer) );
  778. }
  779. if ( CmdFlagOn(rgNetDomArgs, eCommReset) ) {
  780. Win32Err = NetDompResetTime( Domain,
  781. Object,
  782. &DomainUser,
  783. &ObjectUser,
  784. Dc,
  785. CmdFlagOn(rgNetDomArgs, eQueryWksta),
  786. CmdFlagOn(rgNetDomArgs, eQueryServer) );
  787. }
  788. HandleTimeExit:
  789. NetApiBufferFree( Domain );
  790. NetApiBufferFree( Dc );
  791. NetDompFreeAuthIdent( &DomainUser );
  792. NetDompFreeAuthIdent( &ObjectUser );
  793. if (NO_ERROR != Win32Err)
  794. {
  795. NetDompDisplayErrorMessage(Win32Err);
  796. }
  797. return( Win32Err );
  798. }