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.

1964 lines
51 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. sysvol.c
  5. Abstract:
  6. Miscellaneous routines to manage and manipulate the system volume tree
  7. Author:
  8. Mac McLain (MacM) Oct 16, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include <loadfn.h>
  16. #include <ntfrsipi.h>
  17. #include <shlwapi.h>
  18. #include "sysvol.h"
  19. //
  20. // Local function prototypes
  21. //
  22. DWORD
  23. DsRolepCreateSysVolLinks(
  24. IN LPWSTR Path,
  25. IN LPWSTR DnsDomainName
  26. );
  27. DWORD
  28. DsRolepRemoveDirectoryOrLink(
  29. IN LPWSTR Path
  30. );
  31. DWORD
  32. DsRolepTreeCopy(
  33. IN LPWSTR Source,
  34. IN LPWSTR Dest
  35. );
  36. DWORD
  37. DsRolepValidatePath(
  38. IN LPWSTR Path,
  39. IN ULONG ValidationCriteria,
  40. OUT PULONG MatchingCriteria
  41. )
  42. /*++
  43. Routine Description:
  44. This function will validate the path against the specified criteria. This can include
  45. whether it is local or not, whether it is NTFS, etc.
  46. If the function returns success, the MatchingCriteria can be examined to find out which
  47. of the ValidationCriteria are set
  48. Arguments:
  49. Path - Path to validate
  50. ValidationCriteria - What to check for. Refer to DSROLEP_PATH_VALIDATE_*.
  51. MatchingCriteria - This is where the indications of validity are returned. If the path
  52. meets the check, the corresponding bit from the ValidationCriteria is turned on
  53. here.
  54. Returns:
  55. ERROR_SUCCESS - Success
  56. --*/
  57. {
  58. DWORD Win32Err = ERROR_SUCCESS;
  59. DWORD Info, Flags, Len;
  60. WCHAR PathRoot[ 4 ];
  61. WCHAR Type[ 6 ];
  62. DsRolepLogPrint(( DEB_TRACE,
  63. "Validating path %ws.\n",
  64. Path ));
  65. *MatchingCriteria = 0;
  66. if ( FLAG_ON( ValidationCriteria, DSROLEP_PATH_VALIDATE_EXISTENCE ) ) {
  67. Info = GetFileAttributes( Path );
  68. if ( Info == 0xFFFFFFFF ) {
  69. Win32Err = GetLastError();
  70. DsRolepLogPrint(( DEB_ERROR,
  71. "\tCan't get file attributes (%lu)\n",
  72. Win32Err ));
  73. } else if ( FLAG_ON( Info, FILE_ATTRIBUTE_DIRECTORY ) ) {
  74. *MatchingCriteria |= DSROLEP_PATH_VALIDATE_EXISTENCE;
  75. DsRolepLogPrint(( DEB_TRACE,
  76. "\tPath is a directory\n" ));
  77. } else {
  78. DsRolepLogPrint(( DEB_WARN,
  79. "\tPath is a NOT directory\n" ));
  80. }
  81. }
  82. if ( Win32Err == ERROR_SUCCESS ) {
  83. wcsncpy( PathRoot, Path, 3 );
  84. PathRoot[ 3 ] = UNICODE_NULL;
  85. }
  86. if ( Win32Err == ERROR_SUCCESS &&
  87. FLAG_ON( ValidationCriteria, DSROLEP_PATH_VALIDATE_LOCAL ) ) {
  88. Info = GetDriveType( PathRoot );
  89. if ( Info == DRIVE_FIXED ) {
  90. *MatchingCriteria |= DSROLEP_PATH_VALIDATE_LOCAL;
  91. DsRolepLogPrint(( DEB_TRACE,
  92. "\tPath is on a fixed disk drive.\n" ));
  93. } else {
  94. DsRolepLogPrint(( DEB_WARN,
  95. "\tPath is NOT on a fixed disk drive.\n" ));
  96. }
  97. }
  98. if ( Win32Err == ERROR_SUCCESS &&
  99. FLAG_ON( ValidationCriteria, DSROLEP_PATH_VALIDATE_NTFS ) ) {
  100. if ( GetVolumeInformation( PathRoot, NULL, 0, NULL, &Len,
  101. &Flags, Type, sizeof( Type ) / sizeof( WCHAR ) ) == FALSE ) {
  102. Win32Err = GetLastError();
  103. //
  104. // If we've already failed to validate the information, we'll return ERROR_SUCCESS.
  105. //
  106. if ( *MatchingCriteria != ( ValidationCriteria & ~DSROLEP_PATH_VALIDATE_NTFS ) ) {
  107. Win32Err = ERROR_SUCCESS;
  108. } else {
  109. DsRolepLogPrint(( DEB_TRACE,
  110. "\tCan't determine if path is on an NTFS volume.\n" ));
  111. }
  112. } else {
  113. if ( _wcsicmp( Type, L"NTFS" ) == 0 ) {
  114. *MatchingCriteria |= DSROLEP_PATH_VALIDATE_NTFS;
  115. DsRolepLogPrint(( DEB_TRACE,
  116. "\tPath is on an NTFS volume\n" ));
  117. } else {
  118. DsRolepLogPrint(( DEB_WARN,
  119. "\tPath is NOT on an NTFS volume\n" ));
  120. }
  121. }
  122. }
  123. return( Win32Err );
  124. }
  125. #define DSROLEP_SV_SYSVOL L"sysvol"
  126. #define DSROLEP_SV_DOMAIN L"domain"
  127. #define DSROLEP_SV_STAGING_AREA L"staging areas"
  128. #define DSROLEP_SV_STAGING L"staging"
  129. #define DSROLEP_SV_SCRIPTS L"scripts"
  130. #define DSROLEP_LONG_PATH_PREFIX L"\\\\?\\"
  131. DWORD
  132. DsRolepCreateSysVolPath(
  133. IN LPWSTR Path,
  134. IN LPWSTR DnsDomainName,
  135. IN LPWSTR FrsReplicaServer, OPTIONAL
  136. IN LPWSTR Account,
  137. IN LPWSTR Password,
  138. IN PWSTR Site,
  139. IN BOOLEAN FirstDc
  140. )
  141. /*++
  142. Routine Description:
  143. This function will create the system volume tree for use by NTFRS.
  144. Arguments:
  145. Path - Root path under which to create the system volume tree
  146. DnsDomainName - Dns domain name
  147. FrsReplicaServer - The OPTIONAL name of the server to replicate the sysvol from
  148. Site - Site this Dc is in
  149. FirstDc - If TRUE, this is the first Dc in a domain
  150. Returns:
  151. ERROR_SUCCESS - Success
  152. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  153. --*/
  154. {
  155. DWORD Win32Err = ERROR_SUCCESS, Win32Err2;
  156. PWSTR RelativePaths[] = {
  157. DSROLEP_SV_DOMAIN,
  158. DSROLEP_SV_DOMAIN L"\\" DSROLEP_SV_SCRIPTS, // DO NOT CHANGE THIS POSITION without also
  159. // updating ScriptsIndex below
  160. DSROLEP_SV_STAGING_AREA,
  161. DSROLEP_SV_STAGING,
  162. DSROLEP_SV_STAGING L"\\" DSROLEP_SV_DOMAIN,
  163. DSROLEP_SV_SYSVOL // This must always be the last thing
  164. // in the list
  165. };
  166. ULONG ScriptsIndex = 1; // DO NOT CHANGE THIS with out changing the position of the
  167. // DOMAIN\\SCRIPTS entry above
  168. PWSTR CreatePath = NULL, PathEnd = NULL;
  169. PWSTR StagingPath = NULL, StagingPathEnd;
  170. ULONG MaxPathLen, i;
  171. BOOLEAN RootCreated = FALSE;
  172. //
  173. // Make sure the buffer is big enough to hold everything. The
  174. // longest path is the domain root under the staging area
  175. //
  176. MaxPathLen = sizeof( DSROLEP_LONG_PATH_PREFIX ) +
  177. ( wcslen( Path ) * sizeof( WCHAR ) ) +
  178. sizeof( WCHAR ) +
  179. sizeof( DSROLEP_SV_STAGING_AREA ) +
  180. sizeof( WCHAR ) +
  181. ( ( wcslen( DnsDomainName ) + 1 ) * sizeof( WCHAR ) );
  182. CreatePath = RtlAllocateHeap( RtlProcessHeap(), 0, MaxPathLen );
  183. if ( CreatePath == NULL ) {
  184. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  185. } else {
  186. //
  187. // The path exceeds max path, so prepend the \\?\ that allows
  188. // for paths greater than max path
  189. //
  190. if ( MaxPathLen > MAX_PATH * sizeof( WCHAR ) ) {
  191. swprintf( CreatePath,
  192. L"\\\\?\\%ws",
  193. Path );
  194. } else {
  195. wcscpy( CreatePath, Path );
  196. }
  197. }
  198. //
  199. // Create the root path, if it doesn't exist
  200. //
  201. if ( Win32Err == ERROR_SUCCESS ) {
  202. PathEnd = CreatePath + wcslen( CreatePath );
  203. if ( CreateDirectory( CreatePath, NULL ) == FALSE ) {
  204. Win32Err = GetLastError();
  205. if ( Win32Err == ERROR_ALREADY_EXISTS) {
  206. //
  207. // The path exists, so delete it...
  208. //
  209. DsRolepLogPrint(( DEB_TRACE,
  210. "Deleting current sysvol path %ws \n",
  211. CreatePath ));
  212. Win32Err = DsRolepDelnodePath( CreatePath,
  213. MaxPathLen,
  214. FALSE );
  215. if ( Win32Err == ERROR_INVALID_PARAMETER ) {
  216. Win32Err = ERROR_SUCCESS;
  217. }
  218. } else if ( Win32Err == ERROR_ACCESS_DENIED && PathIsRoot(CreatePath) ){
  219. //The sysvol cannot be path at a root directry (i.e. d:\)
  220. //note: d:\sysvol would be legal
  221. DSROLEP_FAIL0( Win32Err, DSROLERES_FAILED_SYSVOL_CANNOT_BE_ROOT_DIRECTORY )
  222. goto Exit;
  223. } else {
  224. DsRolepLogPrint(( DEB_TRACE,
  225. "Failed to create path %ws: %lu\n",
  226. CreatePath,
  227. Win32Err ));
  228. }
  229. } else {
  230. RootCreated = TRUE;
  231. }
  232. }
  233. if ( Win32Err == ERROR_SUCCESS ) {
  234. *PathEnd = L'\\';
  235. PathEnd++;
  236. } else {
  237. //
  238. // Bail, with a specific error
  239. //
  240. DSROLEP_FAIL0( Win32Err, DSROLERES_SYSVOL_DIR_ERROR )
  241. goto Exit;
  242. }
  243. //
  244. // Now, create the rest of the paths...
  245. //
  246. for ( i = 0;
  247. i < sizeof( RelativePaths ) / sizeof( PWSTR ) &&
  248. Win32Err == ERROR_SUCCESS;
  249. i++ ) {
  250. //
  251. // Only create the scripts directory on the first dc
  252. //
  253. if ( i == ScriptsIndex && !FirstDc ) {
  254. continue;
  255. }
  256. wcscpy( PathEnd, RelativePaths[ i ] );
  257. if( CreateDirectory( CreatePath, NULL ) == FALSE ) {
  258. Win32Err = GetLastError();
  259. DsRolepLogPrint(( DEB_TRACE,
  260. "Failed to create path %ws: %lu\n",
  261. CreatePath,
  262. Win32Err ));
  263. break;
  264. }
  265. }
  266. //
  267. // Then, create the symbolic links
  268. //
  269. if ( Win32Err == ERROR_SUCCESS ) {
  270. *PathEnd = UNICODE_NULL;
  271. Win32Err = DsRolepCreateSysVolLinks( Path, DnsDomainName );
  272. }
  273. //
  274. // Prepare for replication of sysvol
  275. //
  276. if ( Win32Err == ERROR_SUCCESS ) {
  277. //
  278. // Make sure the path for the staging area is large enough
  279. //
  280. StagingPath = RtlAllocateHeap( RtlProcessHeap(), 0, MaxPathLen );
  281. if ( StagingPath == NULL ) {
  282. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  283. } else {
  284. //
  285. // The path exceeds max path, so prepend the \\?\ that allows
  286. // for paths greater than max path
  287. //
  288. swprintf( StagingPath,
  289. L"\\\\?\\%ws",
  290. Path );
  291. }
  292. if ( Win32Err == ERROR_SUCCESS ) {
  293. StagingPathEnd = StagingPath + wcslen( StagingPath );
  294. if ( *StagingPathEnd != L'\\' ) {
  295. *StagingPathEnd = L'\\';
  296. StagingPathEnd++;
  297. }
  298. DSROLE_GET_SETUP_FUNC( Win32Err, DsrNtFrsApi_PrepareForPromotionW );
  299. if ( Win32Err == ERROR_SUCCESS ) {
  300. ASSERT( DsrNtFrsApi_PrepareForPromotionW );
  301. Win32Err = ( *DsrNtFrsApi_PrepareForPromotionW )( DsRolepStringErrorUpdateCallback );
  302. if ( Win32Err == ERROR_SUCCESS ) {
  303. //
  304. // Build the domain sysvol
  305. //
  306. swprintf( StagingPathEnd,
  307. L"%ws\\%ws",
  308. DSROLEP_SV_STAGING_AREA,
  309. DnsDomainName );
  310. swprintf( PathEnd,
  311. L"%ws\\%ws",
  312. DSROLEP_SV_SYSVOL,
  313. DnsDomainName );
  314. Win32Err = ( *DsrNtFrsApi_StartPromotionW )(
  315. FrsReplicaServer,
  316. Account,
  317. Password,
  318. DsRolepStringUpdateCallback,
  319. DsRolepStringErrorUpdateCallback,
  320. DnsDomainName,
  321. NTFRSAPI_REPLICA_SET_TYPE_DOMAIN,
  322. FirstDc,
  323. StagingPath,
  324. CreatePath );
  325. if ( Win32Err != ERROR_SUCCESS ) {
  326. DsRolepLogPrint(( DEB_ERROR,
  327. "NtFrsApi_StartPromotionW on %ws / %ws / %ws failed with %lu\n",
  328. DnsDomainName,
  329. StagingPath,
  330. CreatePath,
  331. Win32Err ));
  332. Win32Err2 = DsRolepFinishSysVolPropagation( FALSE, TRUE );
  333. ASSERT( Win32Err2 == ERROR_SUCCESS );
  334. }
  335. } else {
  336. DsRolepLogPrint(( DEB_ERROR,
  337. "NtFrsApi_PrepareForPromotionW failed with %lu\n",
  338. Win32Err ));
  339. }
  340. }
  341. }
  342. }
  343. //
  344. // If something failed, delete the created sysvol tree
  345. //
  346. if ( Win32Err != ERROR_SUCCESS ) {
  347. Win32Err2 = DsRolepDelnodePath( CreatePath,
  348. MaxPathLen,
  349. RootCreated );
  350. if ( Win32Err2 != ERROR_SUCCESS ) {
  351. DsRolepLogPrint(( DEB_TRACE,
  352. "Failed to delete path %ws: %lu\n",
  353. CreatePath,
  354. Win32Err2 ));
  355. }
  356. }
  357. Exit:
  358. //
  359. // Free the path buffers if allocated
  360. //
  361. if ( CreatePath ) {
  362. RtlFreeHeap( RtlProcessHeap(), 0, CreatePath );
  363. }
  364. if ( StagingPath ) {
  365. RtlFreeHeap( RtlProcessHeap(), 0, StagingPath );
  366. }
  367. return( Win32Err );
  368. }
  369. DWORD
  370. DsRolepRemoveSysVolPath(
  371. IN LPWSTR Path,
  372. IN LPWSTR DnsDomainName,
  373. IN GUID *DomainGuid
  374. )
  375. /*++
  376. Routine Description:
  377. This function will remote the create system volume tree
  378. Arguments:
  379. Path - Root path under which to create the system volume tree
  380. DnsDomainName - Dns domain name
  381. DomainGuid - The Guid of the new domain
  382. Returns:
  383. ERROR_SUCCESS - Success
  384. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  385. --*/
  386. {
  387. DWORD Win32Err = ERROR_SUCCESS;
  388. //
  389. // If we can't reset the FRS domain guid, do NOT remove the tree. Otherwise, this
  390. // delete will propagate around!
  391. //
  392. if ( Win32Err == ERROR_SUCCESS ) {
  393. Win32Err = DsRolepDelnodePath( Path, ( wcslen( Path ) + 1 ) * sizeof( WCHAR ), TRUE );
  394. }
  395. return( Win32Err );
  396. }
  397. #define DSROLEP_ALL_STR L"\\*.*"
  398. DWORD
  399. DsRolepDelnodePath(
  400. IN LPWSTR Path,
  401. IN ULONG BufferSize,
  402. IN BOOLEAN DeleteRoot
  403. )
  404. /*++
  405. Routine Description:
  406. This function removes the specified file path
  407. Arguments:
  408. Path - Root path to delete
  409. Returns:
  410. ERROR_SUCCESS - Success
  411. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  412. --*/
  413. {
  414. DWORD Win32Err = ERROR_SUCCESS;
  415. WIN32_FIND_DATA FindData;
  416. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  417. ULONG Len, PathLen = wcslen( Path );
  418. PWSTR FullPath, FindPath;
  419. WCHAR PathBuff[ MAX_PATH + 1];
  420. //
  421. // See if we need to allocate a buffer
  422. //
  423. Len = sizeof( DSROLEP_ALL_STR ) + ( PathLen * sizeof( WCHAR ) );
  424. if ( BufferSize >= Len ) {
  425. FindPath = Path;
  426. wcscat( FindPath, DSROLEP_ALL_STR );
  427. } else {
  428. FindPath = RtlAllocateHeap( RtlProcessHeap(), 0, Len );
  429. if ( FindPath == NULL ) {
  430. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  431. } else {
  432. swprintf( FindPath, L"%ws%ws", Path, DSROLEP_ALL_STR );
  433. }
  434. }
  435. if ( Win32Err == ERROR_SUCCESS ) {
  436. FindHandle = FindFirstFile( FindPath, &FindData );
  437. if ( FindHandle == INVALID_HANDLE_VALUE ) {
  438. Win32Err = GetLastError();
  439. //
  440. // If we get back a path not found error, it's probably a link that we delete the
  441. // supporting storage for. This is not considered an error.
  442. //
  443. if ( Win32Err == ERROR_PATH_NOT_FOUND ) {
  444. Win32Err = ERROR_NO_MORE_FILES;
  445. }
  446. if ( Win32Err != ERROR_SUCCESS && Win32Err != ERROR_NO_MORE_FILES ) {
  447. DsRolepLogPrint(( DEB_ERROR,
  448. "FindFirstFile on %ws failed with %lu\n",
  449. FindPath, Win32Err ));
  450. }
  451. }
  452. }
  453. while ( Win32Err == ERROR_SUCCESS ) {
  454. if ( wcscmp( FindData.cFileName, L"." ) &&
  455. wcscmp( FindData.cFileName, L".." ) ) {
  456. Len = ( wcslen( FindData.cFileName ) + 1 + PathLen + 1 ) * sizeof( WCHAR );
  457. if ( Len > sizeof( FullPath ) ) {
  458. FullPath = RtlAllocateHeap( RtlProcessHeap(), 0, Len );
  459. if ( FullPath == NULL ) {
  460. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  461. }
  462. } else {
  463. FullPath = PathBuff;
  464. }
  465. if ( Win32Err == ERROR_SUCCESS ) {
  466. Path[ PathLen ] = UNICODE_NULL;
  467. swprintf( FullPath, L"%ws\\%ws", Path, FindData.cFileName );
  468. if ( FLAG_ON( FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY ) ) {
  469. Win32Err = DsRolepDelnodePath( FullPath, Len, TRUE );
  470. } else {
  471. //
  472. // Remove the readonly/hidden bits
  473. //
  474. SetFileAttributes( FullPath,
  475. FILE_ATTRIBUTE_NORMAL );
  476. if ( DeleteFileW( FullPath ) == FALSE ) {
  477. Win32Err = GetLastError();
  478. if ( Win32Err != ERROR_SUCCESS ) {
  479. DsRolepLogPrint(( DEB_ERROR,
  480. "DeleteFileW on %ws failed with %lu\n",
  481. FullPath, Win32Err ));
  482. }
  483. }
  484. }
  485. }
  486. if ( FullPath != PathBuff ) {
  487. RtlFreeHeap( RtlProcessHeap(), 0, FullPath );
  488. }
  489. }
  490. if ( Win32Err == ERROR_SUCCESS ) {
  491. if ( FindNextFile( FindHandle, &FindData ) == FALSE ) {
  492. Win32Err = GetLastError();
  493. }
  494. if ( Win32Err != ERROR_SUCCESS && Win32Err != ERROR_NO_MORE_FILES ) {
  495. DsRolepLogPrint(( DEB_ERROR,
  496. "FindNextFile after on %ws failed with %lu\n",
  497. FindData.cFileName, Win32Err ));
  498. }
  499. }
  500. }
  501. //
  502. // Close the handle before trying to remove the directory
  503. //
  504. if ( FindHandle != INVALID_HANDLE_VALUE ) {
  505. FindClose( FindHandle );
  506. }
  507. if ( Win32Err == ERROR_SUCCESS || Win32Err == ERROR_NO_MORE_FILES ) {
  508. Win32Err = ERROR_SUCCESS;
  509. }
  510. //
  511. // Remove the directory
  512. //
  513. if ( DeleteRoot && Win32Err == ERROR_SUCCESS ) {
  514. Win32Err = DsRolepRemoveDirectoryOrLink( Path );
  515. if ( Win32Err != ERROR_SUCCESS ) {
  516. DsRolepLogPrint(( DEB_ERROR,
  517. "Removal of path %ws failed with %lu\n",
  518. Path, Win32Err ));
  519. }
  520. }
  521. //
  522. // Cleanup
  523. //
  524. if ( FindPath != Path ) {
  525. RtlFreeHeap( RtlProcessHeap(), 0, FindPath );
  526. }
  527. return( Win32Err );
  528. }
  529. DWORD
  530. DsRolepRemoveDirectoryOrLink(
  531. IN LPWSTR Path
  532. )
  533. /*++
  534. Routine Description:
  535. This function removes the symbolic link or directory indicated
  536. Arguments:
  537. Path - Path to remove
  538. Returns:
  539. ERROR_SUCCESS - Success
  540. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  541. --*/
  542. {
  543. NTSTATUS Status = STATUS_SUCCESS;
  544. ULONG Attributes;
  545. UNICODE_STRING NtPath;
  546. OBJECT_ATTRIBUTES ObjectAttrs;
  547. HANDLE Handle;
  548. IO_STATUS_BLOCK IOSb;
  549. FILE_DISPOSITION_INFORMATION Disposition = {
  550. TRUE
  551. };
  552. Attributes = GetFileAttributes( Path );
  553. Attributes &= ~( FILE_ATTRIBUTE_HIDDEN |
  554. FILE_ATTRIBUTE_SYSTEM |
  555. FILE_ATTRIBUTE_READONLY );
  556. if ( !SetFileAttributes( Path, Attributes ) ) {
  557. return( GetLastError() );
  558. }
  559. //
  560. // Initialize
  561. //
  562. NtPath.Buffer = NULL;
  563. //
  564. // Convert the name
  565. //
  566. if ( RtlDosPathNameToNtPathName_U( Path, &NtPath, NULL, NULL ) == FALSE ) {
  567. Status = STATUS_INSUFFICIENT_RESOURCES;
  568. }
  569. //
  570. // Open the object
  571. //
  572. if ( NT_SUCCESS( Status ) ) {
  573. InitializeObjectAttributes( &ObjectAttrs, &NtPath, OBJ_CASE_INSENSITIVE, NULL, NULL );
  574. Status = NtOpenFile( &Handle,
  575. SYNCHRONIZE | FILE_READ_DATA | DELETE,
  576. &ObjectAttrs,
  577. &IOSb,
  578. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  579. FILE_OPEN_FOR_BACKUP_INTENT |
  580. FILE_OPEN_REPARSE_POINT |
  581. FILE_SYNCHRONOUS_IO_NONALERT );
  582. if ( NT_SUCCESS( Status ) ) {
  583. Status = NtSetInformationFile( Handle,
  584. &IOSb,
  585. &Disposition,
  586. sizeof( Disposition ),
  587. FileDispositionInformation );
  588. NtClose( Handle );
  589. }
  590. }
  591. //
  592. // Free the memory
  593. //
  594. if ( NtPath.Buffer ) {
  595. RtlFreeUnicodeString( &NtPath );
  596. }
  597. if ( !NT_SUCCESS( Status ) ) {
  598. DsRolepLogPrint(( DEB_ERROR,
  599. "Failed to delete %ws: 0x%lx\n",
  600. Path,
  601. Status ));
  602. }
  603. return( RtlNtStatusToDosError( Status ) );
  604. }
  605. #pragma warning(push)
  606. #pragma warning(disable:4701)
  607. DWORD
  608. DsRolepCreateSymLink(
  609. IN LPWSTR LinkPath,
  610. IN LPWSTR LinkValue
  611. )
  612. {
  613. NTSTATUS Status = STATUS_SUCCESS;
  614. UNICODE_STRING Link, Value, DosValue;
  615. OBJECT_ATTRIBUTES ObjectAttrs;
  616. HANDLE Handle;
  617. IO_STATUS_BLOCK IOSb;
  618. PREPARSE_DATA_BUFFER ReparseBufferHeader = NULL;
  619. PCHAR ReparseBuffer = NULL;
  620. ULONG Len;
  621. //
  622. // Initialize
  623. //
  624. Link.Buffer = NULL;
  625. Value.Buffer = NULL;
  626. //
  627. // Convert the names
  628. //
  629. if ( RtlDosPathNameToNtPathName_U( LinkPath, &Link, NULL, NULL ) ) {
  630. if ( RtlDosPathNameToNtPathName_U( LinkValue, &Value, NULL, NULL ) ) {
  631. RtlInitUnicodeString( &DosValue, LinkValue );
  632. } else {
  633. Status = STATUS_INSUFFICIENT_RESOURCES;
  634. }
  635. } else {
  636. Status = STATUS_INSUFFICIENT_RESOURCES;
  637. }
  638. //
  639. // Open the object
  640. //
  641. if ( NT_SUCCESS( Status ) ) {
  642. InitializeObjectAttributes( &ObjectAttrs, &Link, OBJ_CASE_INSENSITIVE, NULL, NULL );
  643. Status = NtCreateFile( &Handle,
  644. SYNCHRONIZE | FILE_WRITE_DATA,
  645. &ObjectAttrs,
  646. &IOSb,
  647. NULL,
  648. FILE_ATTRIBUTE_NORMAL,
  649. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  650. FILE_OPEN,
  651. FILE_OPEN_REPARSE_POINT,
  652. NULL,
  653. 0 );
  654. if ( NT_SUCCESS( Status ) ) {
  655. Len = ( FIELD_OFFSET( REPARSE_DATA_BUFFER,
  656. MountPointReparseBuffer.PathBuffer ) -
  657. REPARSE_DATA_BUFFER_HEADER_SIZE ) +
  658. Value.Length + sizeof(UNICODE_NULL) +
  659. DosValue.Length + sizeof(UNICODE_NULL);
  660. ReparseBufferHeader = RtlAllocateHeap( RtlProcessHeap(),
  661. 0,
  662. REPARSE_DATA_BUFFER_HEADER_SIZE + Len );
  663. if ( ReparseBufferHeader == NULL ) {
  664. Status = STATUS_INSUFFICIENT_RESOURCES;
  665. } else {
  666. ReparseBufferHeader->ReparseDataLength = (USHORT)Len;
  667. ReparseBufferHeader->Reserved = 0;
  668. ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
  669. ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameLength =
  670. Value.Length;
  671. ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameOffset =
  672. Value.Length + sizeof( UNICODE_NULL );
  673. ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameLength =
  674. DosValue.Length;
  675. RtlCopyMemory( ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer,
  676. Value.Buffer,
  677. Value.Length );
  678. RtlCopyMemory( (PCHAR)(ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer)+
  679. Value.Length + sizeof(UNICODE_NULL),
  680. DosValue.Buffer,
  681. DosValue.Length );
  682. ReparseBufferHeader->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
  683. Status = NtFsControlFile( Handle,
  684. NULL,
  685. NULL,
  686. NULL,
  687. &IOSb,
  688. FSCTL_SET_REPARSE_POINT,
  689. ReparseBufferHeader,
  690. REPARSE_DATA_BUFFER_HEADER_SIZE +
  691. ReparseBufferHeader->ReparseDataLength,
  692. NULL,
  693. 0 );
  694. RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader );
  695. }
  696. NtClose( Handle );
  697. }
  698. }
  699. //
  700. // Free any allocated strings
  701. //
  702. if ( Link.Buffer ) {
  703. RtlFreeUnicodeString( &Link );
  704. }
  705. if ( Value.Buffer ) {
  706. RtlFreeUnicodeString( &Value );
  707. }
  708. if ( !NT_SUCCESS( Status ) ) {
  709. DsRolepLogPrint(( DEB_ERROR,
  710. "Failed to create the link between %ws and %ws: 0x%lx\n",
  711. LinkPath,
  712. LinkValue,
  713. Status ));
  714. }
  715. return( RtlNtStatusToDosError( Status ) );
  716. }
  717. #pragma warning(pop)
  718. DWORD
  719. DsRolepCreateSysVolLinks(
  720. IN LPWSTR Path,
  721. IN PWSTR DnsDomainName
  722. )
  723. /*++
  724. Routine Description:
  725. This function creates the symbolic links used by the system volume tree
  726. Arguments:
  727. Path - Root path under which to create the links
  728. DnsDomainName - The Dns domain name of the new domain
  729. Returns:
  730. ERROR_SUCCESS - Success
  731. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  732. --*/
  733. {
  734. DWORD Win32Err = ERROR_SUCCESS;
  735. WCHAR DestPathBuf[ MAX_PATH + 5];
  736. WCHAR LinkPathBuf[ MAX_PATH + 5];
  737. PWSTR DestPath = DestPathBuf, LinkPath = LinkPathBuf;
  738. PWSTR DestPathEnd = NULL, LinkPathEnd = NULL;
  739. ULONG MaxPathLen, DnsDomainNameSize, Len = wcslen( Path );
  740. if ( * ( Path + Len - 1 ) == L'\\' ) {
  741. Len--;
  742. *( Path + Len ) = UNICODE_NULL;
  743. }
  744. //
  745. // The longest destination path is the path\\staging\\DnsDomainName
  746. //
  747. MaxPathLen = (ULONG)(( sizeof( DSROLEP_SV_STAGING L"\\" ) + 1 ) +
  748. ( ( wcslen ( DnsDomainName ) + 1 ) * sizeof( WCHAR ) ) +
  749. ( ( Len + 5 ) * sizeof( WCHAR ) ));
  750. if ( MaxPathLen > sizeof( DestPathBuf ) / 4 ) {
  751. DestPath = RtlAllocateHeap( RtlProcessHeap(), 0, MaxPathLen );
  752. if ( DestPath == NULL ) {
  753. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  754. } else {
  755. //
  756. // The path exceeds max path, so prepend the \\?\ that allows
  757. // for paths greater than max path
  758. //
  759. swprintf( DestPath,
  760. L"\\\\?\\%ws\\",
  761. Path );
  762. }
  763. } else {
  764. swprintf( DestPath, L"%ws\\", Path );
  765. }
  766. //
  767. // The longest link path is the domain named one
  768. //
  769. if ( Win32Err == ERROR_SUCCESS ) {
  770. DestPathEnd = DestPath + wcslen( DestPath );
  771. DnsDomainNameSize = wcslen( DnsDomainName ) * sizeof( WCHAR );
  772. MaxPathLen = (ULONG)(sizeof( DSROLEP_SV_STAGING_AREA ) + 1 +
  773. sizeof( DSROLEP_SV_SYSVOL ) +
  774. ( ( wcslen( Path ) + 5 ) * sizeof( WCHAR ) )+
  775. DnsDomainNameSize);
  776. if ( MaxPathLen > sizeof( LinkPathBuf ) / 4 ) {
  777. LinkPath = RtlAllocateHeap( RtlProcessHeap(), 0, MaxPathLen );
  778. if ( LinkPath == NULL ) {
  779. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  780. } else {
  781. //
  782. // The path exceeds max path, so prepend the \\?\ that allows
  783. // for paths greater than max path
  784. //
  785. swprintf( LinkPath,
  786. L"\\\\?\\%ws\\%ws\\",
  787. Path,
  788. DSROLEP_SV_SYSVOL );
  789. }
  790. } else {
  791. swprintf( LinkPath, L"%ws\\%ws\\", Path, DSROLEP_SV_SYSVOL );
  792. }
  793. }
  794. //
  795. // Then, the domain path
  796. //
  797. if ( Win32Err == ERROR_SUCCESS ) {
  798. LinkPathEnd = LinkPath + wcslen( LinkPath );
  799. wcscpy( DestPathEnd, DSROLEP_SV_DOMAIN );
  800. wcscpy( LinkPathEnd, DnsDomainName );
  801. if ( CreateDirectory( LinkPath, NULL ) == FALSE ) {
  802. Win32Err = GetLastError();
  803. DsRolepLogPrint(( DEB_ERROR,
  804. "Failed to create the link directory %ws: %lu\n",
  805. LinkPath,
  806. Win32Err ));
  807. } else {
  808. Win32Err = DsRolepCreateSymLink( LinkPath, DestPath );
  809. }
  810. }
  811. //
  812. // Finally, the domain link for the staging area.
  813. //
  814. if ( Win32Err == ERROR_SUCCESS ) {
  815. LinkPathEnd--;
  816. while ( *( LinkPathEnd - 1 ) != L'\\' ) {
  817. LinkPathEnd--;
  818. }
  819. swprintf( DestPathEnd, L"%ws\\%ws", DSROLEP_SV_STAGING, DSROLEP_SV_DOMAIN );
  820. swprintf( LinkPathEnd, L"%ws\\%ws", DSROLEP_SV_STAGING_AREA, DnsDomainName );
  821. if ( CreateDirectory( LinkPath, NULL ) == FALSE ) {
  822. Win32Err = GetLastError();
  823. DsRolepLogPrint(( DEB_ERROR,
  824. "Failed to create the link directory %ws: %lu\n",
  825. LinkPath,
  826. Win32Err ));
  827. } else {
  828. Win32Err = DsRolepCreateSymLink( LinkPath, DestPath );
  829. }
  830. }
  831. //
  832. // Clean up any allocated buffers
  833. //
  834. if ( DestPath != DestPathBuf ) {
  835. RtlFreeHeap( RtlProcessHeap(), 0, DestPath );
  836. }
  837. if ( LinkPath != LinkPathBuf ) {
  838. RtlFreeHeap( RtlProcessHeap(), 0, LinkPath );
  839. }
  840. return( Win32Err );
  841. }
  842. #define DSROLEP_FRS_PATH \
  843. L"\\Registry\\Machine\\System\\CurrentControlSet\\services\\NtFrs\\parameters\\sysvol\\"
  844. #define DSROLEP_FRS_COMMAND L"ReplicaSetCommand"
  845. #define DSROLEP_FRS_NAME L"ReplicaSetName"
  846. #define DSROLEP_FRS_TYPE L"ReplicaSetType"
  847. #define DSROLEP_FRS_SITE L"ReplicaSetSite"
  848. #define DSROLEP_FRS_PRIMARY L"ReplicaSetPrimary"
  849. #define DSROLEP_FRS_STAGE L"ReplicationStagePath"
  850. #define DSROLEP_FRS_ROOT L"ReplicationRootPath"
  851. #define DSROLEP_FRS_CREATE L"Create"
  852. #define DSROLEP_FRS_DELETE L"Delete"
  853. #define DSROLEP_NETLOGON_PATH \
  854. L"System\\CurrentControlSet\\services\\Netlogon\\parameters\\"
  855. #define DSROLEP_NETLOGON_SYSVOL L"SysVol"
  856. #define DSROLEP_NETLOGON_SCRIPTS L"Scripts"
  857. DWORD
  858. DsRolepGetNetlogonScriptsPath(
  859. IN HKEY NetlogonHandle,
  860. OUT LPWSTR *ScriptsPath
  861. )
  862. /*++
  863. Routine Description:
  864. This function reads the old netlogon scripts path and expands it to a valid path
  865. Arguments:
  866. NetlogonHandle - Open handle to the netlogon parameters registry key
  867. ScriptsPath -- Where the expanded path is retunred.
  868. Returns:
  869. ERROR_SUCCESS - Success
  870. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  871. --*/
  872. {
  873. DWORD Win32Err = ERROR_SUCCESS;
  874. PWSTR TempPath = NULL;
  875. ULONG Type, Length = 0;
  876. //
  877. // First, get the current scripts path
  878. //
  879. Win32Err = RegQueryValueEx( NetlogonHandle,
  880. DSROLEP_NETLOGON_SCRIPTS,
  881. 0, // reserved
  882. &Type,
  883. 0,
  884. &Length );
  885. if ( Win32Err == ERROR_SUCCESS ) {
  886. *ScriptsPath = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
  887. if ( *ScriptsPath == NULL ) {
  888. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  889. } else {
  890. Win32Err = RegQueryValueEx( NetlogonHandle,
  891. DSROLEP_NETLOGON_SCRIPTS,
  892. 0,
  893. &Type,
  894. ( PBYTE )*ScriptsPath,
  895. &Length );
  896. if ( Win32Err == ERROR_SUCCESS && Type == REG_EXPAND_SZ ) {
  897. Length = ExpandEnvironmentStrings( *ScriptsPath,
  898. TempPath,
  899. 0 );
  900. if ( Length == 0 ) {
  901. Win32Err = GetLastError();
  902. } else {
  903. TempPath = RtlAllocateHeap( RtlProcessHeap(), 0,
  904. ( Length + 1 ) * sizeof( WCHAR ) );
  905. if ( TempPath == NULL ) {
  906. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  907. } else {
  908. Length = ExpandEnvironmentStrings( *ScriptsPath,
  909. TempPath,
  910. Length );
  911. if ( Length == 0 ) {
  912. Win32Err = GetLastError();
  913. RtlFreeHeap( RtlProcessHeap(), 0, TempPath );
  914. } else {
  915. RtlFreeHeap( RtlProcessHeap(), 0, *ScriptsPath );
  916. *ScriptsPath = TempPath;
  917. }
  918. }
  919. }
  920. }
  921. }
  922. }
  923. return( Win32Err );
  924. }
  925. DWORD
  926. DsRolepSetNetlogonSysVolPath(
  927. IN LPWSTR SysVolRoot,
  928. IN LPWSTR DnsDomainName,
  929. IN BOOLEAN IsUpgrade,
  930. IN OUT PBOOLEAN OkToCleanup
  931. )
  932. /*++
  933. Routine Description:
  934. This function sets the root of the system volume in the Netlogon parameters section
  935. of the registry. The value is set under the key SysVol.
  936. Arguments:
  937. SysVolRoot - Path to the root of the system volume to be set
  938. DnsDomainName - Name of the dns domain name
  939. IsUpgrade - If TRUE, this means that logon scripts are moved
  940. OkToCleanup - A flag is returned here indicating whether the old scripts can be cleaned up
  941. Returns:
  942. ERROR_SUCCESS - Success
  943. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  944. --*/
  945. {
  946. DWORD Win32Err = ERROR_SUCCESS;
  947. HKEY NetlogonHandle = NULL;
  948. PWSTR OldScriptsPath = NULL, NewScriptsPath = NULL, TempPath, FullSysVolPath = NULL;
  949. ULONG Type, Length;
  950. if ( OkToCleanup ) {
  951. *OkToCleanup = FALSE;
  952. }
  953. //
  954. // Build the full scripts path
  955. //
  956. FullSysVolPath = RtlAllocateHeap( RtlProcessHeap(), 0,
  957. ( wcslen( SysVolRoot ) + 1 ) * sizeof( WCHAR ) +
  958. sizeof( DSROLEP_SV_SYSVOL ) );
  959. if ( FullSysVolPath == NULL ) {
  960. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  961. } else {
  962. wcscpy( FullSysVolPath, SysVolRoot );
  963. if ( FullSysVolPath[ wcslen( FullSysVolPath ) - 1 ] != L'\\' ) {
  964. wcscat( FullSysVolPath, L"\\" );
  965. }
  966. wcscat( FullSysVolPath, DSROLEP_SV_SYSVOL );
  967. SysVolRoot = FullSysVolPath;
  968. }
  969. //
  970. // Open the netlogon key
  971. //
  972. if ( Win32Err == ERROR_SUCCESS ) {
  973. Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  974. DSROLEP_NETLOGON_PATH,
  975. 0,
  976. KEY_READ | KEY_WRITE,
  977. &NetlogonHandle );
  978. if ( Win32Err != ERROR_SUCCESS ) {
  979. DsRolepLogPrint(( DEB_ERROR,
  980. "Failed to open %ws: %lu\n", DSROLEP_NETLOGON_PATH, Win32Err ));
  981. return( Win32Err );
  982. }
  983. //
  984. // First, set the sysvol key
  985. //
  986. if ( Win32Err == ERROR_SUCCESS ) {
  987. Win32Err = RegSetValueEx( NetlogonHandle,
  988. DSROLEP_NETLOGON_SYSVOL,
  989. 0,
  990. REG_SZ,
  991. ( CONST PBYTE )SysVolRoot,
  992. ( wcslen( SysVolRoot ) + 1 ) * sizeof( WCHAR ) );
  993. if ( Win32Err != ERROR_SUCCESS ) {
  994. DsRolepLogPrint(( DEB_ERROR,
  995. "Failed to set %ws: %lu\n", DSROLEP_NETLOGON_SYSVOL, Win32Err ));
  996. }
  997. }
  998. }
  999. //
  1000. // If this is an upgrade, move the scripts...
  1001. //
  1002. if ( Win32Err == ERROR_SUCCESS && IsUpgrade ) {
  1003. Win32Err = DsRolepGetNetlogonScriptsPath( NetlogonHandle,
  1004. &OldScriptsPath );
  1005. if ( Win32Err == ERROR_SUCCESS ) {
  1006. //
  1007. // Build the new scripts path
  1008. //
  1009. Length = wcslen( SysVolRoot ) + 1 + wcslen( DnsDomainName ) + 1 +
  1010. ( sizeof( DSROLEP_NETLOGON_SCRIPTS ) / sizeof( WCHAR ) + 1 );
  1011. if ( Length > MAX_PATH ) {
  1012. Length += 5;
  1013. }
  1014. NewScriptsPath = RtlAllocateHeap( RtlProcessHeap(), 0,
  1015. Length * sizeof( WCHAR ) );
  1016. if ( NewScriptsPath == NULL ) {
  1017. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  1018. } else {
  1019. if ( Length > MAX_PATH ) {
  1020. wcscpy( NewScriptsPath, L"\\\\?\\" );
  1021. } else {
  1022. *NewScriptsPath = UNICODE_NULL;
  1023. }
  1024. wcscat( NewScriptsPath, SysVolRoot );
  1025. if ( NewScriptsPath[ wcslen( SysVolRoot ) - 1 ] != L'\\' ) {
  1026. wcscat( NewScriptsPath, L"\\" );
  1027. }
  1028. wcscat( NewScriptsPath, DnsDomainName );
  1029. wcscat( NewScriptsPath, L"\\" );
  1030. wcscat( NewScriptsPath, DSROLEP_NETLOGON_SCRIPTS );
  1031. }
  1032. }
  1033. //
  1034. // Now, the copy...
  1035. //
  1036. if ( Win32Err == ERROR_SUCCESS ) {
  1037. DSROLEP_CURRENT_OP2( DSROLEEVT_MOVE_SCRIPTS, OldScriptsPath, NewScriptsPath );
  1038. Win32Err = DsRolepTreeCopy( OldScriptsPath, NewScriptsPath );
  1039. if ( Win32Err != ERROR_SUCCESS ) {
  1040. DsRolepLogPrint(( DEB_ERROR,
  1041. "DsRolepTreeCopy from %ws to %ws failed with %lu\n",
  1042. OldScriptsPath,
  1043. NewScriptsPath,
  1044. Win32Err ));
  1045. }
  1046. DSROLEP_CURRENT_OP0( DSROLEEVT_SCRIPTS_MOVED );
  1047. }
  1048. if ( Win32Err != ERROR_SUCCESS ) {
  1049. //
  1050. // Raise the an event
  1051. //
  1052. SpmpReportEvent( TRUE,
  1053. EVENTLOG_WARNING_TYPE,
  1054. DSROLERES_FAIL_SCRIPT_COPY,
  1055. 0,
  1056. sizeof( ULONG ),
  1057. &Win32Err,
  1058. 2,
  1059. OldScriptsPath,
  1060. NewScriptsPath );
  1061. DSROLEP_SET_NON_FATAL_ERROR( Win32Err );
  1062. Win32Err = ERROR_SUCCESS;
  1063. }
  1064. RtlFreeHeap( RtlProcessHeap(), 0, OldScriptsPath );
  1065. RtlFreeHeap( RtlProcessHeap(), 0, NewScriptsPath );
  1066. }
  1067. if ( OkToCleanup ) {
  1068. *OkToCleanup = TRUE;
  1069. }
  1070. //
  1071. // Close the handle
  1072. //
  1073. if ( NetlogonHandle ) {
  1074. RegCloseKey( NetlogonHandle );
  1075. }
  1076. RtlFreeHeap( RtlProcessHeap(), 0, FullSysVolPath );
  1077. return( Win32Err );
  1078. }
  1079. DWORD
  1080. DsRolepCleanupOldNetlogonInformation(
  1081. VOID
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. This function cleans up the old netlogon scripts information, including deleting the
  1086. registry key and deleting the old scripts. It should only be called after netlogon has'
  1087. been successfully upgraded
  1088. Arguments:
  1089. Returns:
  1090. ERROR_SUCCESS - Success
  1091. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  1092. --*/
  1093. {
  1094. DWORD Win32Err, Win32Err2;
  1095. HKEY NetlogonHandle = NULL;
  1096. PWSTR OldScriptsPath = NULL;
  1097. DsRolepLogPrint(( DEB_TRACE,
  1098. "Cleaning up old Netlogon information\n"));
  1099. //
  1100. // Open the netlogon key
  1101. //
  1102. Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1103. DSROLEP_NETLOGON_PATH,
  1104. 0,
  1105. KEY_READ | KEY_WRITE,
  1106. &NetlogonHandle );
  1107. if ( Win32Err != ERROR_SUCCESS ) {
  1108. DsRolepLogPrint(( DEB_ERROR,
  1109. "Failed to open %ws: %lu\n", DSROLEP_NETLOGON_PATH, Win32Err ));
  1110. } else {
  1111. Win32Err = DsRolepGetNetlogonScriptsPath( NetlogonHandle,
  1112. &OldScriptsPath );
  1113. if ( ERROR_FILE_NOT_FOUND == Win32Err) {
  1114. Win32Err = ERROR_SUCCESS;
  1115. goto cleanup;
  1116. }
  1117. if ( Win32Err == ERROR_SUCCESS ) {
  1118. Win32Err = DsRolepDelnodePath( OldScriptsPath, wcslen( OldScriptsPath), FALSE );
  1119. }
  1120. //
  1121. // Finally, delete the scripts key
  1122. //
  1123. Win32Err2 = RegDeleteValue( NetlogonHandle, DSROLEP_NETLOGON_SCRIPTS );
  1124. if ( Win32Err2 != ERROR_SUCCESS ) {
  1125. DsRolepLogPrint(( DEB_ERROR,
  1126. "Failed to delete registry key %ws: %lu\n",
  1127. DSROLEP_NETLOGON_SCRIPTS, Win32Err2 ));
  1128. }
  1129. if ( Win32Err == ERROR_SUCCESS ) {
  1130. Win32Err = Win32Err2;
  1131. }
  1132. }
  1133. cleanup:
  1134. if ( NetlogonHandle ) {
  1135. RegCloseKey( NetlogonHandle );
  1136. }
  1137. if ( OldScriptsPath ) {
  1138. RtlFreeHeap( RtlProcessHeap(), 0, OldScriptsPath );
  1139. }
  1140. return( Win32Err );
  1141. }
  1142. DWORD
  1143. DsRolepFinishSysVolPropagation(
  1144. IN BOOLEAN Commit,
  1145. IN BOOLEAN Promote
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. This function will commit or abort an NTFRS initial propagation
  1150. Arguments:
  1151. Commit - If TRUE, the operation is committed. If FALSE, the operation is aborted
  1152. Promote - If TRUE, the operation is a promotion. If FALSE, the operation is a demotion
  1153. Returns:
  1154. ERROR_SUCCESS - Success
  1155. --*/
  1156. {
  1157. DWORD Win32Err = ERROR_SUCCESS;
  1158. if ( Commit ) {
  1159. if ( Promote ) {
  1160. ASSERT( DsrNtFrsApi_WaitForPromotionW );
  1161. Win32Err = ( *DsrNtFrsApi_WaitForPromotionW )( INFINITE,
  1162. DsRolepStringErrorUpdateCallback );
  1163. if ( Win32Err == ERROR_SUCCESS ) {
  1164. ASSERT( DsrNtFrsApi_CommitPromotionW );
  1165. Win32Err = ( *DsrNtFrsApi_CommitPromotionW )( INFINITE,
  1166. DsRolepStringErrorUpdateCallback );
  1167. }
  1168. } else {
  1169. ASSERT( DsrNtFrsApi_WaitForDemotionW );
  1170. Win32Err = ( *DsrNtFrsApi_WaitForDemotionW )( INFINITE,
  1171. DsRolepStringErrorUpdateCallback );
  1172. if ( Win32Err == ERROR_SUCCESS ) {
  1173. ASSERT( DsrNtFrsApi_CommitDemotionW );
  1174. Win32Err = ( *DsrNtFrsApi_CommitDemotionW )( INFINITE,
  1175. DsRolepStringErrorUpdateCallback );
  1176. }
  1177. }
  1178. } else {
  1179. if ( Promote ) {
  1180. ASSERT( DsrNtFrsApi_AbortPromotionW );
  1181. Win32Err = ( *DsrNtFrsApi_AbortPromotionW )();
  1182. } else {
  1183. ASSERT( DsrNtFrsApi_AbortDemotionW );
  1184. Win32Err = ( *DsrNtFrsApi_AbortDemotionW )();
  1185. }
  1186. }
  1187. if ( Win32Err != ERROR_SUCCESS ) {
  1188. DsRolepLogPrint(( DEB_ERROR,
  1189. "DsRolepFinishSysVolPropagation (%S %S) failed with %lu\n",
  1190. Commit ? "Commit" : "Abort",
  1191. Promote ? "Promote" : "Demote",
  1192. Win32Err ));
  1193. }
  1194. return( Win32Err );
  1195. }
  1196. DWORD
  1197. DsRolepAllocAndCopyPath(
  1198. IN LPWSTR Source,
  1199. IN LPWSTR Component,
  1200. OUT LPWSTR *FullPath
  1201. )
  1202. {
  1203. DWORD Win32Err = ERROR_SUCCESS;
  1204. ULONG Len = 0;
  1205. BOOL ExtPath = FALSE;
  1206. Len = wcslen( Source ) + 1 + wcslen( Component ) + 1;
  1207. if ( Len > MAX_PATH ) {
  1208. Len += 5;
  1209. ExtPath = TRUE;
  1210. }
  1211. *FullPath = RtlAllocateHeap( RtlProcessHeap(), 0, Len * sizeof( WCHAR ) );
  1212. if ( *FullPath == NULL ) {
  1213. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  1214. } else {
  1215. if ( ExtPath ) {
  1216. swprintf( *FullPath, L"\\\\?\\%ws\\%ws", Source, Component );
  1217. } else {
  1218. swprintf( *FullPath, L"%ws\\%ws", Source, Component );
  1219. }
  1220. }
  1221. return( Win32Err );
  1222. }
  1223. DWORD
  1224. DsRolepTreeCopy(
  1225. IN LPWSTR Source,
  1226. IN LPWSTR Dest
  1227. )
  1228. /*++
  1229. Routine Description:
  1230. This function will do a tree copy from the source directory to the destination
  1231. Arguments:
  1232. Source - Source dir
  1233. Dest - Dest dir
  1234. Returns:
  1235. ERROR_SUCCESS - Success
  1236. --*/
  1237. {
  1238. DWORD Win32Err = ERROR_SUCCESS;
  1239. WIN32_FIND_DATA FindData;
  1240. PWSTR SourcePath = NULL, DestPath = NULL, TempPath;
  1241. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  1242. //
  1243. // Build the path for findfirst/findnext
  1244. //
  1245. Win32Err = DsRolepAllocAndCopyPath( Source,
  1246. L"*.*",
  1247. &SourcePath );
  1248. if ( Win32Err != ERROR_SUCCESS ) {
  1249. goto TreeCopyError;
  1250. }
  1251. //
  1252. // Now, enumerate the paths
  1253. //
  1254. FindHandle = FindFirstFile( SourcePath, &FindData );
  1255. if ( FindHandle == INVALID_HANDLE_VALUE ) {
  1256. Win32Err = GetLastError();
  1257. DsRolepLogPrint(( DEB_ERROR,
  1258. "FindFirstFile on %ws failed with %lu\n",
  1259. Source, Win32Err ));
  1260. goto TreeCopyError;
  1261. }
  1262. while ( Win32Err == ERROR_SUCCESS ) {
  1263. if ( wcscmp( FindData.cFileName, L"." ) &&
  1264. wcscmp( FindData.cFileName, L".." ) ) {
  1265. //
  1266. // Build the source path
  1267. //
  1268. Win32Err = DsRolepAllocAndCopyPath( Source,
  1269. FindData.cFileName,
  1270. &TempPath );
  1271. if ( Win32Err == ERROR_SUCCESS ) {
  1272. RtlFreeHeap( RtlProcessHeap(), 0, SourcePath );
  1273. SourcePath = TempPath;
  1274. } else {
  1275. goto TreeCopyError;
  1276. }
  1277. //
  1278. // Build the destination path
  1279. //
  1280. Win32Err = DsRolepAllocAndCopyPath( Dest,
  1281. FindData.cFileName,
  1282. &TempPath );
  1283. if ( Win32Err == ERROR_SUCCESS ) {
  1284. RtlFreeHeap( RtlProcessHeap(), 0, DestPath );
  1285. DestPath = TempPath;
  1286. } else {
  1287. goto TreeCopyError;
  1288. }
  1289. //
  1290. // Now, either do the copy, or copy the directory
  1291. //
  1292. if ( FLAG_ON( FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY ) ) {
  1293. if ( CreateDirectory( DestPath, NULL ) == FALSE ) {
  1294. Win32Err = GetLastError();
  1295. DsRolepLogPrint(( DEB_ERROR,
  1296. "CreateDirectory on %ws failed with %lu\n",
  1297. DestPath, Win32Err ));
  1298. } else {
  1299. Win32Err = DsRolepTreeCopy( SourcePath, DestPath );
  1300. }
  1301. } else {
  1302. if ( CopyFile( SourcePath, DestPath, FALSE ) == FALSE ) {
  1303. Win32Err = GetLastError();
  1304. DsRolepLogPrint(( DEB_ERROR,
  1305. "CopyFile from %ws to %ws failed with %lu\n",
  1306. SourcePath, DestPath, Win32Err ));
  1307. }
  1308. }
  1309. }
  1310. if ( Win32Err == ERROR_SUCCESS ) {
  1311. if ( FindNextFile( FindHandle, &FindData ) == FALSE ) {
  1312. Win32Err = GetLastError();
  1313. }
  1314. if ( Win32Err != ERROR_SUCCESS && Win32Err != ERROR_NO_MORE_FILES ) {
  1315. DsRolepLogPrint(( DEB_ERROR,
  1316. "FindNextFile after on %ws failed with %lu\n",
  1317. FindData.cFileName, Win32Err ));
  1318. }
  1319. }
  1320. }
  1321. TreeCopyError:
  1322. //
  1323. // Close the handle
  1324. //
  1325. if ( FindHandle != INVALID_HANDLE_VALUE ) {
  1326. FindClose( FindHandle );
  1327. }
  1328. if ( Win32Err == ERROR_NO_MORE_FILES ) {
  1329. Win32Err = ERROR_SUCCESS;
  1330. }
  1331. //
  1332. // Cleanup
  1333. //
  1334. if ( SourcePath ) {
  1335. RtlFreeHeap( RtlProcessHeap(), 0, SourcePath );
  1336. }
  1337. if ( DestPath ) {
  1338. RtlFreeHeap( RtlProcessHeap(), 0, DestPath );
  1339. }
  1340. return( Win32Err );
  1341. }