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.

3492 lines
116 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. threadman.c
  5. Abstract:
  6. Implementation of the thread and thread management routines
  7. Author:
  8. Mac McLain (MacM) Feb 10, 1997
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include <setpch.h>
  14. #include <dssetp.h>
  15. #include <dsgetdc.h>
  16. #include <lmcons.h>
  17. #include <lmapibuf.h>
  18. #include <lmsname.h>
  19. #include <loadfn.h>
  20. #include <lsarpc.h>
  21. #include <db.h>
  22. #include <lsasrvmm.h>
  23. #include <lsaisrv.h>
  24. #include <lmaccess.h>
  25. #include <netsetp.h>
  26. #include <samrpc.h> // for samisrv.h
  27. #include <samisrv.h> // for nlrepl.h
  28. #include <nlrepl.h> // for I_NetNotifyDsChange
  29. #include <Lmshare.h> // for NetShareDel()
  30. #include <autoenr.h> // for CertAutoRemove()
  31. #include "secure.h"
  32. #include "services.h"
  33. #include "upgrade.h"
  34. #include "trustdom.h"
  35. #include "sysvol.h"
  36. #include "lsa.h"
  37. #include "ds.h"
  38. #include "threadman.h"
  39. // forward from setutl.h
  40. DWORD
  41. DsRolepDeregisterNetlogonDnsRecords(
  42. PNTDS_DNS_RR_INFO pInfo
  43. );
  44. //
  45. // Helpful macros
  46. //
  47. #define DSROLEP_MAKE_DNS_RELATIVE(name) \
  48. if(name) { \
  49. DWORD _StripAbsoluteLength_ = wcslen( name ); \
  50. if ( *(name + _StripAbsoluteLength_ - 1 ) == L'.' ) { \
  51. *(name + _StripAbsoluteLength_ - 1 ) = UNICODE_NULL; \
  52. } \
  53. }
  54. #define DSROLEP_ALLOC_AND_COPY_STRING_EXIT( dest, src, label ) \
  55. if ( (src) ) { \
  56. (dest) = RtlAllocateHeap( RtlProcessHeap(), 0, (wcslen( (src) ) + 1) * sizeof( WCHAR ) ); \
  57. if ( !(dest) ) { \
  58. goto label; \
  59. } else { \
  60. wcscpy((dest), (src)); \
  61. } \
  62. } else { \
  63. (dest) = NULL; \
  64. }
  65. #define DSROLEP_ALLOC_BYTES( dest, src, size, label ) \
  66. if ( (src) ) { \
  67. (dest) = RtlAllocateHeap( RtlProcessHeap(), 0, (size)); \
  68. if ( !(dest) ) { \
  69. goto label; \
  70. } \
  71. } else { \
  72. (dest) = NULL; \
  73. }
  74. #define DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( dest, src, label ) \
  75. if ( (src) && (src)->Buffer ) { \
  76. (dest)->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, (src)->MaximumLength ); \
  77. if ( (dest)->Buffer == NULL ) { \
  78. goto label; \
  79. } else { \
  80. (dest)->Length = (src)->Length; \
  81. (dest)->MaximumLength = (src)->MaximumLength; \
  82. RtlCopyMemory( (dest)->Buffer, (src)->Buffer, (src)->MaximumLength ); \
  83. } \
  84. } else { \
  85. RtlZeroMemory( (dest), sizeof( UNICODE_STRING ) ); \
  86. }
  87. //
  88. // Function definitions
  89. //
  90. DWORD
  91. DsRolepBuildPromoteArgumentBlock(
  92. IN LPWSTR DnsDomainName,
  93. IN LPWSTR FlatDomainName,
  94. IN LPWSTR SiteName,
  95. IN LPWSTR DsDatabasePath,
  96. IN LPWSTR DsLogPath,
  97. IN IFM_SYSTEM_INFO * pIfmSystemInfo,
  98. IN LPWSTR SystemVolumeRootPath,
  99. IN PUNICODE_STRING Bootkey,
  100. IN LPWSTR Parent,
  101. IN LPWSTR Server,
  102. IN LPWSTR Account,
  103. IN PUNICODE_STRING Password,
  104. IN PUNICODE_STRING DomainAdminPassword,
  105. IN PUNICODE_STRING SafeModePassword,
  106. IN ULONG Options,
  107. IN UCHAR PasswordSeed,
  108. IN OUT PDSROLEP_OPERATION_PROMOTE_ARGS *Promote
  109. )
  110. /*++
  111. Routine Description:
  112. Builds an argument structure to pass into one of the promote worker functions. Since the
  113. rpc call will return before the thread completes, we'll have to copy all our argument strings.
  114. Since parameters may be changed through out the course of promotion, we assume allocations
  115. are made from the process heap.
  116. Resultant argument block should be freed via DsRolepFreeArgumentBlock
  117. Arguments:
  118. DnsDomainName - Dns domain name of the domain to install
  119. FlatDomainName - Flat (NetBIOS) domain name of the domain to install
  120. SiteName - Name of the site this DC should belong to
  121. DsDatabasePath - Absolute path on the local machine where the Ds DIT should go
  122. DsLogPath - Absolute path on the local machine where the Ds log files should go
  123. pIfmSystemInfo - Information about the IFM system and restore media used to
  124. dcpromo off. If NULL, not an IFM promotion.
  125. SystemVolumeRootPath - Absolute path on the local machine to be the root of the system
  126. volume root path.
  127. Bootkey - Needed when you don't have the key in the registry or on a disk
  128. cbBootkey - size of the bootkey
  129. Parent - Optional. Parent domain name
  130. Server -- Optional. Replica partner or server in parent domain
  131. Account - User account to use when setting up as a child domain
  132. Password - Password to use with the above account
  133. DomainAdminPassword - Password to set the domain administartor account
  134. Options - Options to control the creation of the domain
  135. PasswordSeed - Seed used to hide the passwords
  136. Promote - Where the allocated argument block is returned
  137. Returns:
  138. ERROR_SUCCESS - Success
  139. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  140. --*/
  141. {
  142. DWORD WinError = ERROR_NOT_ENOUGH_MEMORY;
  143. *Promote = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( DSROLEP_OPERATION_PROMOTE_ARGS ) );
  144. if ( *Promote == NULL ) {
  145. goto BuildPromoteDone;
  146. }
  147. RtlZeroMemory( *Promote, sizeof( DSROLEP_OPERATION_PROMOTE_ARGS ) );
  148. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->DnsDomainName, DnsDomainName, BuildPromoteDone );
  149. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->FlatDomainName, FlatDomainName, BuildPromoteDone );
  150. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->SiteName, SiteName, BuildPromoteDone );
  151. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->DsDatabasePath, DsDatabasePath, BuildPromoteDone );
  152. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->DsLogPath, DsLogPath, BuildPromoteDone );
  153. (*Promote)->pIfmSystemInfo = pIfmSystemInfo; // guaranteed to be good through promotion.
  154. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->SysVolRootPath, SystemVolumeRootPath, BuildPromoteDone );
  155. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->Parent, Parent, BuildPromoteDone );
  156. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->Server, Server, BuildPromoteDone );
  157. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Promote)->Account, Account, BuildPromoteDone );
  158. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Promote)->Password), Password,
  159. BuildPromoteDone );
  160. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Promote)->DomainAdminPassword),
  161. DomainAdminPassword, BuildPromoteDone );
  162. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Promote)->SafeModePassword),
  163. SafeModePassword, BuildPromoteDone );
  164. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Promote)->Bootkey),
  165. Bootkey, BuildPromoteDone );
  166. (*Promote)->Options = Options;
  167. (*Promote)->Decode = PasswordSeed;
  168. WinError = DsRolepGetImpersonationToken( &(*Promote)->ImpersonateToken );
  169. BuildPromoteDone:
  170. if ( WinError != ERROR_SUCCESS ) {
  171. DsRolepFreeArgumentBlock( Promote, TRUE );
  172. }
  173. return( WinError );
  174. }
  175. DWORD
  176. DsRolepBuildDemoteArgumentBlock(
  177. IN DSROLE_SERVEROP_DEMOTE_ROLE ServerRole,
  178. IN LPWSTR DnsDomainName,
  179. IN LPWSTR Account,
  180. IN PUNICODE_STRING Password,
  181. IN ULONG Options,
  182. IN BOOL LastDcInDomain,
  183. IN ULONG cRemoveNCs,
  184. IN LPWSTR * pszRemoveNCs,
  185. IN PUNICODE_STRING AdminPassword,
  186. IN UCHAR PasswordSeed,
  187. IN OUT PDSROLEP_OPERATION_DEMOTE_ARGS *Demote
  188. )
  189. /*++
  190. Routine Description:
  191. Builds an argument structure to pass into the demote worker functions. Since the rpc call
  192. will return before the thread completes, we'll have to copy all our argument strings.
  193. Resultant argument block should be freed via DsRolepFreeArgumentBlock
  194. Arguments:
  195. ServerRole - New role for the server
  196. DnsDomainName - Dns domain name of the domain to uninstall. NULL means all of them
  197. Account - User account to use when setting up as a child domain
  198. Password - Password to use with the above account
  199. Options - Options to control the creation of the domain
  200. LastDcInDomain - If TRUE, the Dc being demoted is the last Dc in the domain.
  201. AdminPassword - Password to set on the administrator account if it is a new install
  202. PasswordSeed - Seed used to hide the passwords
  203. Demote - Where the allocated argument block is returned
  204. Returns:
  205. ERROR_SUCCESS - Success
  206. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  207. --*/
  208. {
  209. DWORD WinError = ERROR_NOT_ENOUGH_MEMORY;
  210. ULONG i;
  211. *Demote = RtlAllocateHeap( RtlProcessHeap(), 0, sizeof( DSROLEP_OPERATION_DEMOTE_ARGS ) );
  212. if ( *Demote == NULL ) {
  213. goto BuildDemoteDone;
  214. }
  215. RtlZeroMemory( *Demote, sizeof( DSROLEP_OPERATION_DEMOTE_ARGS ) );
  216. (*Demote)->ServerRole = ServerRole;
  217. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Demote)->DomainName, DnsDomainName, BuildDemoteDone );
  218. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Demote)->Account, Account, BuildDemoteDone );
  219. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Demote)->Password), Password, BuildDemoteDone );
  220. (*Demote)->LastDcInDomain = ( LastDcInDomain != 0 );
  221. (*Demote)->cRemoveNCs = cRemoveNCs;
  222. DSROLEP_ALLOC_BYTES( (*Demote)->pszRemoveNCs, pszRemoveNCs, (cRemoveNCs * sizeof(LPWSTR)), BuildDemoteDone );
  223. for(i = 0; i < cRemoveNCs; i++){
  224. DSROLEP_ALLOC_AND_COPY_STRING_EXIT( (*Demote)->pszRemoveNCs[i], pszRemoveNCs[i], BuildDemoteDone );
  225. }
  226. DSROLEP_ALLOC_AND_COPY_UNICODE_STRING_EXIT( &((*Demote)->AdminPassword),
  227. AdminPassword,
  228. BuildDemoteDone );
  229. (*Demote)->Options = Options;
  230. (*Demote)->Decode = PasswordSeed;
  231. WinError = DsRolepGetImpersonationToken( & (*Demote)->ImpersonateToken );
  232. BuildDemoteDone:
  233. if ( WinError != ERROR_SUCCESS ) {
  234. DsRolepFreeArgumentBlock( Demote, FALSE );
  235. }
  236. return( WinError );
  237. }
  238. VOID
  239. DsRolepFreeArgumentBlock(
  240. IN PVOID *ArgumentBlock,
  241. IN BOOLEAN Promote
  242. )
  243. /*++
  244. Routine Description:
  245. Frees an arugment block allocated via DsRolepBuildPromote/DemoteArgumentBlock
  246. Since parameters may be changed through out the course of promotion, we assume allocations
  247. are made from the process heap.
  248. Arguments:
  249. ArgumentBlock - Argument block to free
  250. Promote - If TRUE, this is a promote argument block. If FALSE, it's a demote arg block
  251. Returns:
  252. VOID
  253. --*/
  254. {
  255. PDSROLEP_OPERATION_PROMOTE_ARGS PromoteArg;
  256. PDSROLEP_OPERATION_DEMOTE_ARGS Demote;
  257. PVOID HeapHandle = RtlProcessHeap();
  258. ULONG i;
  259. if ( !ArgumentBlock ) {
  260. return;
  261. }
  262. //
  263. // Free it all
  264. //
  265. if ( Promote ) {
  266. PromoteArg = ( PDSROLEP_OPERATION_PROMOTE_ARGS )*ArgumentBlock;
  267. RtlFreeHeap( HeapHandle, 0, PromoteArg->DnsDomainName );
  268. RtlFreeHeap( HeapHandle, 0, PromoteArg->FlatDomainName );
  269. RtlFreeHeap( HeapHandle, 0, PromoteArg->SiteName );
  270. RtlFreeHeap( HeapHandle, 0, PromoteArg->DsDatabasePath );
  271. RtlFreeHeap( HeapHandle, 0, PromoteArg->DsLogPath );
  272. RtlFreeHeap( HeapHandle, 0, PromoteArg->SysVolRootPath );
  273. RtlFreeHeap( HeapHandle, 0, PromoteArg->Parent );
  274. RtlFreeHeap( HeapHandle, 0, PromoteArg->Server );
  275. RtlFreeHeap( HeapHandle, 0, PromoteArg->Account );
  276. RtlFreeHeap( HeapHandle, 0, PromoteArg->Password.Buffer );
  277. RtlFreeHeap( HeapHandle, 0, PromoteArg->DomainAdminPassword.Buffer );
  278. if ( PromoteArg->ImpersonateToken ) {
  279. NtClose( PromoteArg->ImpersonateToken );
  280. }
  281. } else {
  282. Demote = ( PDSROLEP_OPERATION_DEMOTE_ARGS )*ArgumentBlock;
  283. RtlFreeHeap( HeapHandle, 0, Demote->Account );
  284. RtlFreeHeap( HeapHandle, 0, Demote->Password.Buffer );
  285. RtlFreeHeap( HeapHandle, 0, Demote->DomainName );
  286. RtlFreeHeap( HeapHandle, 0, Demote->AdminPassword.Buffer );
  287. for(i = 0; i < Demote->cRemoveNCs; i++){
  288. RtlFreeHeap( HeapHandle, 0, Demote->pszRemoveNCs[i] );
  289. }
  290. RtlFreeHeap( HeapHandle, 0, Demote->pszRemoveNCs );
  291. if ( Demote->ImpersonateToken ) {
  292. NtClose( Demote->ImpersonateToken );
  293. }
  294. }
  295. RtlFreeHeap( HeapHandle, 0, *ArgumentBlock );
  296. }
  297. DWORD
  298. DsRolepSpinWorkerThread(
  299. IN DSROLEP_OPERATION_TYPE Operation,
  300. IN PVOID ArgumentBlock
  301. )
  302. /*++
  303. Routine Description:
  304. This function actually creates the worker thread that will do the promot/demote
  305. Arguments:
  306. Operation - Demote, Promote as DC, or Promote as Replica
  307. ArgumentBlock - Block of arguments appropriate for the operation
  308. Returns:
  309. ERROR_SUCCESS - Success
  310. INVALID_PARAMETER - An unexpected operation type encounterd
  311. --*/
  312. {
  313. DWORD WinError = ERROR_SUCCESS, IgnoreError;
  314. NTSTATUS NtStatus;
  315. DWORD ThreadId;
  316. //
  317. // The basic premise is that we'll utilize the Completion event to indicate when
  318. // the thread is full initialized.
  319. //
  320. NtStatus = NtResetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  321. WinError = RtlNtStatusToDosError( NtStatus );
  322. if ( ERROR_SUCCESS == WinError ) {
  323. switch ( Operation) {
  324. case DSROLEP_OPERATION_DC:
  325. DsRolepCurrentOperationHandle.OperationThread = CreateThread(
  326. NULL,
  327. 0,
  328. ( LPTHREAD_START_ROUTINE )DsRolepThreadPromoteDc,
  329. ArgumentBlock,
  330. 0,
  331. &ThreadId );
  332. break;
  333. case DSROLEP_OPERATION_REPLICA:
  334. DsRolepCurrentOperationHandle.OperationThread = CreateThread(
  335. NULL,
  336. 0,
  337. ( LPTHREAD_START_ROUTINE )DsRolepThreadPromoteReplica,
  338. ArgumentBlock,
  339. 0,
  340. &ThreadId );
  341. break;
  342. case DSROLEP_OPERATION_DEMOTE:
  343. DsRolepCurrentOperationHandle.OperationThread = CreateThread(
  344. NULL,
  345. 0,
  346. ( LPTHREAD_START_ROUTINE )DsRolepThreadDemote,
  347. ArgumentBlock,
  348. 0,
  349. &ThreadId );
  350. break;
  351. default:
  352. DsRoleDebugOut(( DEB_ERROR,
  353. "Unexpected operation %lu encountered\n", Operation ));
  354. WinError = ERROR_INVALID_PARAMETER;
  355. break;
  356. }
  357. //
  358. // Check for failure
  359. //
  360. if ( WinError == ERROR_SUCCESS &&
  361. DsRolepCurrentOperationHandle.OperationThread == NULL ) {
  362. WinError = GetLastError();
  363. }
  364. //
  365. // If it worked, wait for the thread to indicate its ready
  366. //
  367. if ( WinError == ERROR_SUCCESS ) {
  368. if ( WaitForSingleObject( DsRolepCurrentOperationHandle.CompletionEvent,
  369. INFINITE ) == WAIT_FAILED ) {
  370. WinError = GetLastError();
  371. } else {
  372. NtResetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  373. }
  374. }
  375. }
  376. if ( WinError == ERROR_SUCCESS ) {
  377. DsRoleDebugOut(( DEB_TRACE,
  378. "Thread %lu successfully started\n", ThreadId ));
  379. } else {
  380. DsRolepLogPrint(( DEB_ERROR,
  381. "Thread %lu unsuccessfully started: %lu\n", ThreadId, WinError ));
  382. }
  383. return( WinError );
  384. }
  385. DWORD
  386. DsRolepThreadPromoteDc(
  387. IN PVOID ArgumentBlock
  388. )
  389. /*++
  390. Routine Description:
  391. This function actually "promotes" a server to a dc of an new domain. Additionally, this
  392. domain can be set up as a child of an existing domain. This is accomplished by:
  393. Installing the Ds as a replica
  394. Setting the DnsDomainTree LSA information
  395. Optionally configuring it as a child of an existing domain
  396. Configuring the KDC
  397. Arguments:
  398. ArgumentBlock - Block of arguments appropriate for the operation
  399. Returns:
  400. ERROR_SUCCESS - Success
  401. --*/
  402. {
  403. DWORD WinError = ERROR_SUCCESS;
  404. DWORD IgnoreError;
  405. PWSTR ParentDc = NULL;
  406. PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
  407. PDSROLEP_OPERATION_PROMOTE_ARGS PromoteArgs = ( PDSROLEP_OPERATION_PROMOTE_ARGS )ArgumentBlock;
  408. DSROLEP_DOMAIN_POLICY_INFO BackupDomainPolicyInfo;
  409. ULONG FindOptions;
  410. GUID DomainGuid;
  411. PWSTR InstalledSite = NULL;
  412. PSID NewDomainSid = NULL;
  413. PPOLICY_DNS_DOMAIN_INFO ParentDnsDomainInfo = NULL;
  414. PWSTR DnsDomainTreeName = NULL;
  415. //
  416. // BOOLEAN's to maintain state
  417. //
  418. // N.B. The order of these booleans is the order in which they
  419. // are changed -- please maintain order and make sure that
  420. // the PromoteUndo section undoes them in the reverse order
  421. //
  422. BOOLEAN IPCConnection = FALSE; // resource -- release on exit
  423. BOOLEAN RestartNetlogon = FALSE;
  424. BOOLEAN SysVolCreated = FALSE;
  425. BOOLEAN CleanupNetlogon = FALSE; // nothing to undo
  426. BOOLEAN DsInstalled = FALSE;
  427. BOOLEAN DsRunning = FALSE;
  428. BOOLEAN DomainPolicyInfoChanged = FALSE;
  429. BOOLEAN DomainServicesChanged = FALSE;
  430. BOOLEAN DomainControllerServicesChanged = FALSE;
  431. BOOLEAN TrustCreated = FALSE;
  432. BOOLEAN ProductTypeChanged = FALSE;
  433. //
  434. // Init the stack space
  435. //
  436. RtlZeroMemory(&BackupDomainPolicyInfo, sizeof(BackupDomainPolicyInfo));
  437. //
  438. // Set our event to indicate we're starting
  439. //
  440. NtSetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  441. //
  442. // If we have an existing domain in the forest to install from and we
  443. // weren't given a site or source server name, we need to make a dsgetdc
  444. // name.
  445. //
  446. if ( PromoteArgs->Server ) {
  447. ParentDc = PromoteArgs->Server;
  448. }
  449. if ( PromoteArgs->Parent != NULL &&
  450. ( (PromoteArgs->Server == NULL)
  451. || (PromoteArgs->SiteName == NULL) ) ) {
  452. DsRolepLogPrint(( DEB_TRACE,
  453. "No source DC or no site name specified. Searching for dc in domain %ws: ( DS_REQUIRED | WRITABLE )\n",
  454. PromoteArgs->Parent ));
  455. DSROLEP_CURRENT_OP1( DSROLEEVT_SEARCH_DC, PromoteArgs->Parent );
  456. FindOptions = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_FORCE_REDISCOVERY | DS_RETURN_DNS_NAME;
  457. WinError = DsGetDcName(NULL,
  458. PromoteArgs->Parent,
  459. NULL,
  460. NULL,
  461. FindOptions,
  462. &DomainControllerInfo );
  463. if ( ERROR_SUCCESS != WinError ) {
  464. DsRolepLogPrint(( DEB_TRACE,
  465. "Couldn't find domain controller in domain %ws (error: %d)\n",
  466. ParentDc,
  467. WinError ));
  468. if ( PromoteArgs->Server == NULL ) {
  469. //
  470. // This is a fatal error if we can't find a dc in the parent domain
  471. // If we have a server, then we can derive a site name later on if
  472. // necessary
  473. //
  474. DSROLEP_FAIL1( WinError, DSROLERES_FIND_DC, PromoteArgs->Parent );
  475. DsRolepLogPrint(( DEB_ERROR,
  476. "Failed to find a dc for %ws: %lu\n",
  477. PromoteArgs->Parent,
  478. WinError ));
  479. goto PromoteUndo;
  480. }
  481. //
  482. // This isn't fatal since we are a source server
  483. //
  484. DsRolepLogPrint(( DEB_TRACE, "Using supplied domain controller: %ws\n", ParentDc ));
  485. WinError = ERROR_SUCCESS;
  486. } else {
  487. //
  488. // The dsgetdcname succeeded
  489. //
  490. if ( PromoteArgs->Server == NULL ) {
  491. //
  492. // Use the found domain controller
  493. //
  494. DSROLEP_CURRENT_OP2( DSROLEEVT_FOUND_DC,
  495. PromoteArgs->Parent,
  496. ParentDc );
  497. DsRolepLogPrint(( DEB_TRACE_DS, "No user specified source DC\n" ));
  498. ParentDc = DomainControllerInfo->DomainControllerName;
  499. }
  500. //
  501. // Determine the site that we are going to be installed in
  502. // the results of the parent query
  503. //
  504. if ( PromoteArgs->SiteName == NULL ) {
  505. DsRolepLogPrint(( DEB_TRACE_DS, "No user specified site\n" ));
  506. PromoteArgs->SiteName = DomainControllerInfo->ClientSiteName;
  507. if ( (PromoteArgs->SiteName == NULL)
  508. && (!_wcsicmp(ParentDc, DomainControllerInfo->DomainControllerName)) ) {
  509. DsRolepLogPrint(( DEB_TRACE_DS, "This machine is not in a configured site ... using source DC's site.\n" ));
  510. PromoteArgs->SiteName = DomainControllerInfo->DcSiteName;
  511. } else {
  512. //
  513. // We can't find a site. That's ok -- the ds will find one for
  514. // us
  515. //
  516. }
  517. }
  518. if ( PromoteArgs->SiteName ) {
  519. DSROLEP_CURRENT_OP2( DSROLEEVT_FOUND_SITE,
  520. PromoteArgs->SiteName,
  521. PromoteArgs->Parent );
  522. } else {
  523. DsRolepLogPrint(( DEB_TRACE_DS, "This machine is not in a configured site\n" ));
  524. }
  525. }
  526. } else {
  527. //
  528. // The caller supplied both the source server and site name
  529. //
  530. ParentDc = PromoteArgs->Server;
  531. DsRolepLogPrint(( DEB_TRACE, "Using supplied domain controller: %ws\n", ParentDc ));
  532. DsRolepLogPrint(( DEB_TRACE, "Using supplied site: %ws\n", PromoteArgs->SiteName ));
  533. }
  534. //
  535. // Ok, we have determined the our source domain controller and destination
  536. // site
  537. //
  538. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  539. //
  540. // Force the time synch
  541. //
  542. if ( ParentDc
  543. && FLAG_ON( PromoteArgs->Options, DSROLE_DC_FORCE_TIME_SYNC ) ) {
  544. WinError = DsRolepForceTimeSync( PromoteArgs->ImpersonateToken,
  545. ParentDc );
  546. if ( ERROR_SUCCESS != WinError ) {
  547. DsRolepLogPrint(( DEB_WARN, "Time sync with %ws failed with %d\n",
  548. ParentDc,
  549. WinError ));
  550. //
  551. // This is not a fatal error
  552. //
  553. WinError = ERROR_SUCCESS;
  554. }
  555. }
  556. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  557. //
  558. // If we are setting up a child domain, establish a session first
  559. //
  560. if ( ParentDc ) {
  561. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  562. WinError = ImpNetpManageIPCConnect( PromoteArgs->ImpersonateToken,
  563. ParentDc,
  564. PromoteArgs->Account,
  565. PromoteArgs->Password.Buffer,
  566. NETSETUPP_CONNECT_IPC );
  567. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  568. if ( ERROR_SUCCESS != WinError ) {
  569. DSROLEP_FAIL1( WinError, DSROLERES_NET_USE, ParentDc );
  570. DsRolepLogPrint(( DEB_ERROR,
  571. "Failed to establish the session with %ws: 0x%lx\n", ParentDc,
  572. WinError ));
  573. goto PromoteUndo;
  574. }
  575. IPCConnection = TRUE;
  576. }
  577. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  578. //
  579. // If we have a parent dc, get the LSA policy from it
  580. //
  581. //
  582. // Strip the trailing '.' from the Dns name if we happen to have an absolute name
  583. //
  584. DSROLEP_MAKE_DNS_RELATIVE( PromoteArgs->DnsDomainName );
  585. DnsDomainTreeName = PromoteArgs->DnsDomainName;
  586. if ( ParentDc ) {
  587. NTSTATUS Status;
  588. UNICODE_STRING ParentServer;
  589. HANDLE ParentPolicy = NULL;
  590. OBJECT_ATTRIBUTES ObjectAttributes;
  591. DSROLEP_CURRENT_OP1( DSROLEEVT_MACHINE_POLICY, ParentDc );
  592. RtlInitUnicodeString( &ParentServer, ParentDc );
  593. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  594. Status = ImpLsaOpenPolicy( PromoteArgs->ImpersonateToken,
  595. &ParentServer,
  596. &ObjectAttributes,
  597. MAXIMUM_ALLOWED,
  598. &ParentPolicy );
  599. if ( NT_SUCCESS( Status ) ) {
  600. Status = ImpLsaQueryInformationPolicy( PromoteArgs->ImpersonateToken,
  601. ParentPolicy,
  602. PolicyDnsDomainInformation,
  603. &ParentDnsDomainInfo );
  604. ImpLsaClose( PromoteArgs->ImpersonateToken, ParentPolicy );
  605. }
  606. //
  607. // We'll have to build it as a NULL terminated string
  608. //
  609. if ( NT_SUCCESS( Status ) && ParentDnsDomainInfo->DnsForestName.Length ) {
  610. if ( ParentDnsDomainInfo->DnsForestName.Buffer[
  611. ParentDnsDomainInfo->DnsForestName.Length / sizeof( WCHAR ) ] == UNICODE_NULL ) {
  612. DnsDomainTreeName = ( PWSTR )ParentDnsDomainInfo->DnsForestName.Buffer;
  613. } else {
  614. DnsDomainTreeName = RtlAllocateHeap(
  615. RtlProcessHeap(), 0,
  616. ParentDnsDomainInfo->DnsForestName.Length + sizeof( WCHAR ) );
  617. if ( DnsDomainTreeName == NULL ) {
  618. Status = STATUS_INSUFFICIENT_RESOURCES;
  619. } else {
  620. RtlCopyMemory( DnsDomainTreeName,
  621. ParentDnsDomainInfo->DnsForestName.Buffer,
  622. ParentDnsDomainInfo->DnsForestName.Length );
  623. DnsDomainTreeName[ ParentDnsDomainInfo->DnsForestName.Length /
  624. sizeof( WCHAR ) ] = UNICODE_NULL;
  625. }
  626. }
  627. }
  628. WinError = RtlNtStatusToDosError( Status );
  629. DSROLEP_FAIL1( WinError, DSROLERES_POLICY_READ_REMOTE, ParentDc );
  630. if ( ERROR_SUCCESS != WinError ) {
  631. goto PromoteUndo;
  632. }
  633. }
  634. //
  635. // If we are doing a root install, make sure we were given the forest root
  636. // as our parent
  637. //
  638. if ( FLAG_ON( PromoteArgs->Options, DSROLE_DC_TRUST_AS_ROOT ) ) {
  639. DSROLEP_MAKE_DNS_RELATIVE( PromoteArgs->Parent );
  640. DSROLEP_MAKE_DNS_RELATIVE( DnsDomainTreeName );
  641. if ( _wcsicmp( PromoteArgs->Parent, DnsDomainTreeName ) ) {
  642. //
  643. // Names don't match... We can't allow this...
  644. //
  645. DsRolepLogPrint(( DEB_ERROR,
  646. "Tried to specify domain %ws as a forest root but "
  647. "%ws is the actual root\n",
  648. PromoteArgs->Parent,
  649. DnsDomainTreeName ));
  650. WinError = ERROR_INVALID_DOMAINNAME;
  651. DSROLEP_FAIL1( WinError, DSROLERES_NOT_FOREST_ROOT, PromoteArgs->Parent );
  652. goto PromoteUndo;
  653. }
  654. }
  655. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  656. //
  657. // Make a back up of the local policy...
  658. //
  659. WinError = DsRolepBackupDomainPolicyInfo( NULL, &BackupDomainPolicyInfo );
  660. if ( ERROR_SUCCESS != WinError ) {
  661. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_READ_LOCAL );
  662. goto PromoteUndo;
  663. }
  664. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  665. //
  666. // Stop netlogon
  667. //
  668. DSROLEP_CURRENT_OP1( DSROLEEVT_STOP_SERVICE, SERVICE_NETLOGON );
  669. WinError = DsRolepStopNetlogon( &RestartNetlogon );
  670. if ( ERROR_SUCCESS != WinError ) {
  671. DsRolepLogPrint(( DEB_WARN, "Failed to stop NETLOGON (%d)\n", WinError ));
  672. goto PromoteUndo;
  673. }
  674. DsRolepLogPrint(( DEB_TRACE, "Stopped NETLOGON\n" ));
  675. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  676. //
  677. // Create the system volume information so we can seed the system volume while the Ds is
  678. // installing
  679. //
  680. DSROLEP_CURRENT_OP1( DSROLEEVT_CREATE_SYSVOL, PromoteArgs->SysVolRootPath );
  681. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  682. WinError = DsRolepCreateSysVolPath( PromoteArgs->SysVolRootPath,
  683. PromoteArgs->DnsDomainName,
  684. ParentDc,
  685. PromoteArgs->Account,
  686. PromoteArgs->Password.Buffer,
  687. PromoteArgs->SiteName,
  688. TRUE );
  689. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  690. DSROLEP_CURRENT_OP1( DSROLEEVT_SVSETUP, PromoteArgs->SysVolRootPath );
  691. if ( WinError != ERROR_SUCCESS ) {
  692. DsRolepLogPrint(( DEB_ERROR, "Failed to create the system volume (%d)\n", WinError ));
  693. goto PromoteUndo;
  694. }
  695. SysVolCreated = TRUE;
  696. DsRolepLogPrint(( DEB_TRACE, "Created the system volume\n" ));
  697. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  698. //
  699. // Setup the Ds
  700. //
  701. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  702. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->DomainAdminPassword );
  703. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->SafeModePassword );
  704. WinError = DsRolepInstallDs( PromoteArgs->DnsDomainName,
  705. PromoteArgs->FlatDomainName,
  706. DnsDomainTreeName,
  707. PromoteArgs->SiteName,
  708. PromoteArgs->DsDatabasePath,
  709. PromoteArgs->DsLogPath,
  710. PromoteArgs->pIfmSystemInfo,
  711. PromoteArgs->SysVolRootPath,
  712. &(PromoteArgs->Bootkey),
  713. PromoteArgs->DomainAdminPassword.Buffer,
  714. PromoteArgs->Parent,
  715. ParentDc,
  716. PromoteArgs->Account,
  717. PromoteArgs->Password.Buffer,
  718. PromoteArgs->SafeModePassword.Buffer,
  719. PromoteArgs->Parent,
  720. PromoteArgs->Options,
  721. FALSE,
  722. PromoteArgs->ImpersonateToken,
  723. &InstalledSite,
  724. &DomainGuid,
  725. &NewDomainSid );
  726. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  727. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->DomainAdminPassword );
  728. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->SafeModePassword );
  729. if ( ERROR_SUCCESS != WinError ) {
  730. DsRolepLogPrint(( DEB_ERROR, "Failed to install the directory service (%d)\n", WinError ));
  731. goto PromoteUndo;
  732. }
  733. DsRunning = TRUE;
  734. DsInstalled = TRUE;
  735. DsRolepLogPrint(( DEB_TRACE, "Installed the directory service\n", WinError ));
  736. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  737. //
  738. // Set the LSA domain policy
  739. //
  740. WinError = DsRolepSetLsaDomainPolicyInfo( PromoteArgs->DnsDomainName,
  741. PromoteArgs->FlatDomainName,
  742. DnsDomainTreeName,
  743. &DomainGuid,
  744. NewDomainSid,
  745. NTDS_INSTALL_DOMAIN,
  746. &BackupDomainPolicyInfo );
  747. if ( ERROR_SUCCESS != WinError ) {
  748. DsRolepLogPrint(( DEB_ERROR, "Failed to set the LSA policy (%d)\n", WinError ));
  749. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_WRITE_LOCAL );
  750. goto PromoteUndo;
  751. }
  752. DomainPolicyInfoChanged = TRUE;
  753. DsRolepLogPrint(( DEB_TRACE, "Set the LSA policy\n"));
  754. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  755. //
  756. // Configure the domain relative services
  757. //
  758. WinError = DsRolepConfigureDomainServices( DSROLEP_SERVICES_ON );
  759. if ( WinError != ERROR_SUCCESS ) {
  760. DsRolepLogPrint(( DEB_ERROR, "Failed to configure the domain services (%d)\n", WinError ));
  761. goto PromoteUndo;
  762. }
  763. DomainServicesChanged = TRUE;
  764. DsRolepLogPrint(( DEB_TRACE, "Configured the domain services\n" ));
  765. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  766. //
  767. // Configure the domain controller relative services
  768. //
  769. WinError = DsRolepConfigureDomainControllerServices( DSROLEP_SERVICES_ON );
  770. if ( WinError != ERROR_SUCCESS ) {
  771. DsRolepLogPrint(( DEB_ERROR, "Failed to configure the domain controller services (%d)\n", WinError ));
  772. goto PromoteUndo;
  773. }
  774. DomainControllerServicesChanged = TRUE;
  775. DsRolepLogPrint(( DEB_TRACE, "Configured the domain controller services\n" ));
  776. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  777. //
  778. // Finally, upgrade the Lsa to the Ds.
  779. //
  780. WinError = DsRolepUpgradeLsaToDs( TRUE );
  781. if ( ERROR_SUCCESS != WinError ) {
  782. DSROLEP_FAIL0( WinError, DSROLERES_LSA_UPGRADE );
  783. DsRolepLogOnFailure( WinError,
  784. DsRolepLogPrint(( DEB_TRACE,
  785. "Upgrade of the LSA into the DS failed with %lu\n",
  786. WinError )) );
  787. goto PromoteUndo;
  788. }
  789. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  790. //
  791. // Create the trust objects and set the DnsDomainTree information
  792. //
  793. if ( ParentDc ) {
  794. WinError = DsRolepCreateTrustedDomainObjects( PromoteArgs->ImpersonateToken,
  795. ParentDc,
  796. PromoteArgs->DnsDomainName,
  797. ParentDnsDomainInfo,
  798. PromoteArgs->Options );
  799. if ( WinError != ERROR_SUCCESS ) {
  800. DsRolepLogPrint(( DEB_ERROR, "Failed to create trusted domain objects (%d)\n", WinError ));
  801. goto PromoteUndo;
  802. }
  803. TrustCreated = TRUE;
  804. DsRolepLogPrint(( DEB_TRACE, "Created trusted domain objects\n" ));
  805. }
  806. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  807. //
  808. // Create the GPO for policy
  809. //
  810. WinError = ( *DsrSceDcPromoCreateGPOsInSysvolEx )( PromoteArgs->ImpersonateToken,
  811. PromoteArgs->DnsDomainName,
  812. PromoteArgs->SysVolRootPath,
  813. FLAG_ON( PromoteArgs->Options,
  814. DSROLE_DC_DOWNLEVEL_UPGRADE ) ?
  815. SCE_PROMOTE_FLAG_UPGRADE :
  816. 0,
  817. DsRolepStringUpdateCallback );
  818. if ( ERROR_SUCCESS != WinError ) {
  819. DSROLEP_FAIL1( WinError, DSROLERES_GPO_CREATION, PromoteArgs->DnsDomainName );
  820. DsRolepLogOnFailure( WinError,
  821. DsRolepLogPrint(( DEB_TRACE,
  822. "Creation of GPO failed with %lu\n",
  823. WinError )) );
  824. goto PromoteUndo;
  825. }
  826. DsRolepLogPrint(( DEB_TRACE,
  827. "Created GPO\n" ));
  828. //
  829. // Stop the Ds
  830. //
  831. DsRolepStopDs( DsRunning );
  832. DsRunning = FALSE;
  833. //
  834. // If the install succeeded, make sure to save off the new site name
  835. //
  836. WinError = DsRolepSetOperationHandleSiteName( InstalledSite );
  837. if ( WinError != ERROR_SUCCESS ) {
  838. DsRolepLogPrint(( DEB_ERROR, "Failed to copy site name (%d)\n", WinError ));
  839. goto PromoteUndo;
  840. }
  841. //
  842. // If we update it, NULL out the local parameter so we don't attempt to delete it
  843. //
  844. InstalledSite = NULL;
  845. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  846. //
  847. // Set the computers Dns domain name
  848. //
  849. DSROLEP_CURRENT_OP1( DSROLEEVT_SET_COMPUTER_DNS, PromoteArgs->DnsDomainName );
  850. WinError = NetpSetDnsComputerNameAsRequired( PromoteArgs->DnsDomainName );
  851. if ( ERROR_SUCCESS != WinError ) {
  852. DsRolepLogOnFailure( WinError,
  853. DsRolepLogPrint(( DEB_TRACE,
  854. "NetpSetDnsComputerNameAsRequired to %ws failed with %lu\n",
  855. PromoteArgs->DnsDomainName,
  856. WinError )) );
  857. DSROLEP_FAIL1( WinError, DSROLERES_SET_COMPUTER_DNS, PromoteArgs->DnsDomainName );
  858. goto PromoteUndo;
  859. }
  860. //
  861. // Restart netlogon if it was stopped and if a failure occurred
  862. //
  863. //
  864. // Complete the sysvol replication
  865. //
  866. WinError = DsRolepFinishSysVolPropagation( TRUE, TRUE );
  867. if ( ERROR_SUCCESS != WinError ) {
  868. DsRolepLogPrint(( DEB_ERROR, "Failed to complete system volume replication (%d)\n", WinError ));
  869. goto PromoteUndo;
  870. }
  871. DsRolepLogPrint(( DEB_TRACE, "Completed system volume replication\n"));
  872. //
  873. // Next, set the sysvol path for netlogon
  874. //
  875. WinError = DsRolepSetNetlogonSysVolPath( PromoteArgs->SysVolRootPath,
  876. PromoteArgs->DnsDomainName,
  877. ( BOOLEAN )FLAG_ON( PromoteArgs->Options,
  878. DSROLE_DC_DOWNLEVEL_UPGRADE ),
  879. &CleanupNetlogon );
  880. if ( ERROR_SUCCESS != WinError ) {
  881. DsRolepLogPrint(( DEB_ERROR, "Failed to set system volume path for NETLOGON (%d)\n", WinError ));
  882. goto PromoteUndo;
  883. }
  884. DsRolepLogPrint(( DEB_TRACE, "Set system volume path for NETLOGON\n" ));
  885. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  886. //
  887. // Set the machine role
  888. //
  889. WinError = DsRolepSetProductType( DSROLEP_MT_MEMBER );
  890. if ( ERROR_SUCCESS != WinError ) {
  891. DsRolepLogPrint(( DEB_ERROR, "Failed to set the product type (%d)\n", WinError ));
  892. goto PromoteUndo;
  893. }
  894. ProductTypeChanged = TRUE;
  895. DsRolepLogPrint(( DEB_TRACE, "Set the product type\n" ));
  896. //
  897. // Set the security on the dc files
  898. //
  899. WinError = DsRolepSetDcSecurity( PromoteArgs->ImpersonateToken,
  900. PromoteArgs->SysVolRootPath,
  901. PromoteArgs->DsDatabasePath,
  902. PromoteArgs->DsLogPath,
  903. ( BOOLEAN )FLAG_ON( PromoteArgs->Options,
  904. DSROLE_DC_DOWNLEVEL_UPGRADE ),
  905. FALSE );
  906. if ( ERROR_SUCCESS != WinError ) {
  907. DsRolepLogPrint(( DEB_ERROR, "Failed to set security on domain controller (%d)\n", WinError ));
  908. goto PromoteUndo;
  909. }
  910. DsRolepLogPrint(( DEB_TRACE, "Set security on domain controller\n"));
  911. DsRolepSetCriticalOperationsDone();
  912. //
  913. // From here to do the end, perform, and only perform, non critical
  914. // operations
  915. //
  916. //
  917. // Indicate that we are no longer doing upgrades, if applicable
  918. //
  919. if ( FLAG_ON( PromoteArgs->Options, DSROLE_DC_DOWNLEVEL_UPGRADE ) ) {
  920. WinError = DsRolepDeleteUpgradeInfo();
  921. DsRolepLogOnFailure( WinError,
  922. DsRolepLogPrint(( DEB_WARN,
  923. "Failed to cleanup upgrade info (%d)\n",
  924. WinError )) );
  925. if (ERROR_SUCCESS == WinError) {
  926. DsRolepLogPrint(( DEB_TRACE,
  927. "Removed upgrade info\n" ));
  928. }
  929. // This error isn't interesting to propogate
  930. WinError = ERROR_SUCCESS;
  931. }
  932. //
  933. // Remove any old netlogon stuff if we got that far
  934. //
  935. if ( CleanupNetlogon ) {
  936. WinError = DsRolepCleanupOldNetlogonInformation();
  937. DsRolepLogOnFailure( WinError,
  938. DsRolepLogPrint(( DEB_WARN,
  939. "Failed to cleanup old netlogon information (%d)\n",
  940. WinError )) );
  941. if (ERROR_SUCCESS == WinError) {
  942. DsRolepLogPrint(( DEB_TRACE,
  943. "Removed old netlogon information\n" ));
  944. }
  945. // This error isn't interesting to propogate
  946. WinError = ERROR_SUCCESS;
  947. }
  948. //
  949. // Set the default logon domain to the current domain name
  950. //
  951. WinError = DsRolepSetLogonDomain( PromoteArgs->FlatDomainName, FALSE );
  952. if ( ERROR_SUCCESS != WinError ) {
  953. DsRolepLogOnFailure( WinError,
  954. DsRolepLogPrint(( DEB_WARN,
  955. "Failed to set default logon domain to %ws (%d)\n",
  956. PromoteArgs->FlatDomainName,
  957. WinError )) );
  958. if (ERROR_SUCCESS == WinError) {
  959. DsRolepLogPrint(( DEB_TRACE,
  960. "Set default logon domain to %ws\n",
  961. PromoteArgs->FlatDomainName ));
  962. }
  963. //
  964. // This is no reason to fail
  965. //
  966. WinError = ERROR_SUCCESS;
  967. }
  968. //
  969. // Notify the time server we have completed the promotion
  970. //
  971. {
  972. DWORD dwTimeFlags = W32TIME_PROMOTE;
  973. if ( FLAG_ON( PromoteArgs->Options, DSROLE_DC_TRUST_AS_ROOT )
  974. || (NULL == PromoteArgs->Parent) ) {
  975. //
  976. // Any tree root, including the root of the forest
  977. // should have this flag.
  978. //
  979. dwTimeFlags |= W32TIME_PROMOTE_FIRST_DC_IN_TREE;
  980. }
  981. (*DsrW32TimeDcPromo)( dwTimeFlags );
  982. }
  983. //
  984. // By this time, we have successfully completed the promotion operation
  985. //
  986. ASSERT( ERROR_SUCCESS == WinError );
  987. PromoteExit:
  988. // The DS should not be running at this point
  989. ASSERT( FALSE == DsRunning );
  990. //
  991. // Release any resources
  992. //
  993. //
  994. // Tear down the session to the parent, if we have one
  995. //
  996. if ( IPCConnection ) {
  997. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  998. IgnoreError = ImpNetpManageIPCConnect( PromoteArgs->ImpersonateToken,
  999. ParentDc,
  1000. PromoteArgs->Account,
  1001. PromoteArgs->Password.Buffer,
  1002. (NETSETUPP_DISCONNECT_IPC | NETSETUPP_USE_LOTS_FORCE));
  1003. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  1004. if ( IgnoreError != ERROR_SUCCESS ) {
  1005. DsRolepLogPrint(( DEB_WARN,
  1006. "Failed to destroy the session with %ws: 0x%lx\n", ParentDc,
  1007. IgnoreError ));
  1008. }
  1009. IPCConnection = FALSE;
  1010. }
  1011. if ( ParentDnsDomainInfo ) {
  1012. if ( DnsDomainTreeName != ParentDnsDomainInfo->DnsForestName.Buffer ) {
  1013. RtlFreeHeap( RtlProcessHeap(), 0, DnsDomainTreeName );
  1014. }
  1015. LsaFreeMemory( ParentDnsDomainInfo );
  1016. }
  1017. if ( InstalledSite ) {
  1018. RtlFreeHeap( RtlProcessHeap(), 0, InstalledSite );
  1019. }
  1020. if ( NewDomainSid ) {
  1021. RtlFreeHeap( RtlProcessHeap(), 0, NewDomainSid );
  1022. }
  1023. DsRolepFreeDomainPolicyInfo( &BackupDomainPolicyInfo );
  1024. if ( DomainControllerInfo != NULL ) {
  1025. if ( PromoteArgs->SiteName == DomainControllerInfo->DcSiteName ||
  1026. PromoteArgs->SiteName == DomainControllerInfo->ClientSiteName ) {
  1027. PromoteArgs->SiteName = NULL;
  1028. }
  1029. NetApiBufferFree( DomainControllerInfo );
  1030. }
  1031. DsRolepFreeArgumentBlock( &ArgumentBlock, TRUE );
  1032. //
  1033. // Reset our operation handle and set the final operation status
  1034. //
  1035. DsRolepSetOperationDone( DSROLEP_OP_PROMOTION, WinError );
  1036. ExitThread( WinError );
  1037. return( WinError );
  1038. PromoteUndo:
  1039. //
  1040. // Something must have failed if we are undoing
  1041. //
  1042. ASSERT( WinError != ERROR_SUCCESS );
  1043. if ( ProductTypeChanged ) {
  1044. IgnoreError = DsRolepSetProductType( DSROLEP_MT_STANDALONE );
  1045. DsRolepLogOnFailure( IgnoreError,
  1046. DsRolepLogPrint(( DEB_WARN,
  1047. "Failed to rollback product type (%d)\n",
  1048. IgnoreError )) );
  1049. ProductTypeChanged = FALSE;
  1050. }
  1051. if ( TrustCreated ) {
  1052. IgnoreError = DsRolepRemoveTrustedDomainObjects( PromoteArgs->ImpersonateToken,
  1053. ParentDc,
  1054. ParentDnsDomainInfo,
  1055. FLAG_ON( PromoteArgs->Options,
  1056. DSROLE_DC_PARENT_TRUST_EXISTS ) ?
  1057. 0 :
  1058. DSROLE_DC_DELETE_PARENT_TRUST );
  1059. DsRolepLogOnFailure( IgnoreError,
  1060. DsRolepLogPrint(( DEB_WARN,
  1061. "Failed to rollback trusted domain object creations (%d)\n",
  1062. IgnoreError )) );
  1063. TrustCreated = FALSE;
  1064. }
  1065. if ( DomainControllerServicesChanged ) {
  1066. IgnoreError = DsRolepConfigureDomainControllerServices( DSROLEP_SERVICES_REVERT );
  1067. DsRolepLogOnFailure( IgnoreError,
  1068. DsRolepLogPrint(( DEB_WARN,
  1069. "Failed to rollback domain controller services configuration (%d)\n",
  1070. IgnoreError )) );
  1071. DomainControllerServicesChanged = FALSE;
  1072. }
  1073. if ( DomainServicesChanged ) {
  1074. IgnoreError = DsRolepConfigureDomainServices( DSROLEP_SERVICES_REVERT );
  1075. DsRolepLogOnFailure( IgnoreError,
  1076. DsRolepLogPrint(( DEB_WARN,
  1077. "Failed to rollback domain services configuration (%d)\n",
  1078. IgnoreError )) );
  1079. DomainServicesChanged = FALSE;
  1080. }
  1081. if ( DomainPolicyInfoChanged ) {
  1082. IgnoreError = DsRolepRestoreDomainPolicyInfo(&BackupDomainPolicyInfo);
  1083. DsRolepLogOnFailure( IgnoreError,
  1084. DsRolepLogPrint(( DEB_WARN,
  1085. "Failed to rollback domain policy information (%d)\n",
  1086. IgnoreError )) );
  1087. DomainPolicyInfoChanged = FALSE;
  1088. }
  1089. if ( DsRunning ) {
  1090. IgnoreError = DsRolepStopDs( DsRunning );
  1091. DsRolepLogOnFailure( IgnoreError,
  1092. DsRolepLogPrint(( DEB_WARN,
  1093. "Failed to stop the directory service (%d)\n",
  1094. IgnoreError )) );
  1095. DsRunning = FALSE;
  1096. }
  1097. if ( DsInstalled ) {
  1098. IgnoreError = DsRolepUninstallDs( );
  1099. DsRolepLogOnFailure( IgnoreError,
  1100. DsRolepLogPrint(( DEB_WARN,
  1101. "Failed to rollback directory service installation (%d)\n",
  1102. IgnoreError )) );
  1103. DsInstalled = FALSE;
  1104. }
  1105. if ( SysVolCreated ) {
  1106. IgnoreError = DsRolepFinishSysVolPropagation( FALSE, TRUE );
  1107. DsRolepLogOnFailure( IgnoreError,
  1108. DsRolepLogPrint(( DEB_WARN,
  1109. "Failed to abort system volume installation (%d)\n",
  1110. IgnoreError )) );
  1111. IgnoreError = DsRolepRemoveSysVolPath( PromoteArgs->SysVolRootPath,
  1112. PromoteArgs->DnsDomainName,
  1113. &DomainGuid );
  1114. DsRolepLogOnFailure( IgnoreError,
  1115. DsRolepLogPrint(( DEB_WARN,
  1116. "Failed to remove system volume path (%d)\n",
  1117. IgnoreError )) );
  1118. SysVolCreated = FALSE;
  1119. }
  1120. if ( RestartNetlogon ) {
  1121. IgnoreError = DsRolepStartNetlogon();
  1122. DsRolepLogOnFailure( IgnoreError,
  1123. DsRolepLogPrint(( DEB_WARN,
  1124. "Failed to restart netlogon (%d)\n",
  1125. IgnoreError )) );
  1126. RestartNetlogon = FALSE;
  1127. }
  1128. //
  1129. // We are finished the undo -- exit the thread
  1130. //
  1131. ASSERT( ERROR_SUCCESS != WinError );
  1132. goto PromoteExit;
  1133. }
  1134. DWORD
  1135. DsRolepThreadPromoteReplica(
  1136. IN PVOID ArgumentBlock
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. This function actually "promotes" a server to a replica of an existing domain. This is
  1141. accomplished by:
  1142. Installing the Ds as a replica
  1143. Setting the DnsDomainTree LSA information
  1144. Configuring the KDC
  1145. Required are the Dns domain name and the name of a replica within the domain, and the
  1146. Db and Log paths
  1147. Arguments:
  1148. ArgumentBlock - Block of arguments appropriate for the operation
  1149. Returns:
  1150. ERROR_SUCCESS - Success
  1151. --*/
  1152. {
  1153. DWORD WinError = ERROR_SUCCESS, IgnoreError;
  1154. PDSROLEP_OPERATION_PROMOTE_ARGS PromoteArgs = (PDSROLEP_OPERATION_PROMOTE_ARGS)ArgumentBlock;
  1155. PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
  1156. PDOMAIN_CONTROLLER_INFO ClientSiteInfo = NULL;
  1157. DSROLEP_DOMAIN_POLICY_INFO BackupDomainPolicyInfo;
  1158. ULONG FindOptions = 0;
  1159. GUID DomainGuid;
  1160. PWSTR InstalledSite = NULL, ReplicaServer = NULL;
  1161. PSID NewDomainSid = NULL;
  1162. WCHAR LocalMachineAccountName[ MAX_COMPUTERNAME_LENGTH + 2 ];
  1163. ULONG Length = MAX_COMPUTERNAME_LENGTH + 1;
  1164. //
  1165. // BOOLEAN's to maintain state
  1166. //
  1167. // N.B. The order of these booleans is the order in which they
  1168. // are changed -- please maintain order and make sure that
  1169. // the PromoteUndo section undoes them in the reverse order
  1170. //
  1171. BOOLEAN IPCConnection = FALSE; // resource -- release on exit
  1172. BOOLEAN RestartNetlogon = FALSE;
  1173. BOOLEAN SysVolCreated = FALSE;
  1174. BOOLEAN DsInstalled = FALSE;
  1175. BOOLEAN DsRunning = FALSE;
  1176. BOOLEAN DomainPolicyInfoChanged = FALSE;
  1177. BOOLEAN DomainControllerServicesChanged = FALSE;
  1178. BOOLEAN ProductTypeChanged = FALSE;
  1179. RtlZeroMemory(&BackupDomainPolicyInfo, sizeof(BackupDomainPolicyInfo));
  1180. //
  1181. // Set our event to indicate we're starting
  1182. //
  1183. NtSetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  1184. //
  1185. // Get the account name
  1186. //
  1187. if ( GetComputerName( LocalMachineAccountName, &Length ) == FALSE ) {
  1188. WinError = GetLastError();
  1189. DsRolepLogPrint(( DEB_ERROR, "Failed to get computer name (%d)\n", WinError ));
  1190. goto PromoteUndo;
  1191. } else {
  1192. wcscat( LocalMachineAccountName, L"$" );
  1193. }
  1194. //
  1195. // Strip the trailing '.' from the Dns name if we happen to have an absolute name
  1196. //
  1197. DSROLEP_MAKE_DNS_RELATIVE( PromoteArgs->DnsDomainName );
  1198. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1199. if (PromoteArgs->Server) {
  1200. WinError = DsRolepTimeSyncAndManageIPCConnect((PVOID)PromoteArgs,
  1201. PromoteArgs->Server);
  1202. if ( WinError != ERROR_SUCCESS ) {
  1203. goto PromoteUndo;
  1204. }
  1205. ReplicaServer = PromoteArgs->Server;
  1206. IPCConnection = TRUE;
  1207. }
  1208. //
  1209. // Find the server that holds the machine account for this machine
  1210. //
  1211. FindOptions = DS_DIRECTORY_SERVICE_REQUIRED | DS_WRITABLE_REQUIRED | DS_FORCE_REDISCOVERY |
  1212. DS_RETURN_DNS_NAME;
  1213. WinError = ImpDsRolepDsGetDcForAccount( PromoteArgs->ImpersonateToken,
  1214. PromoteArgs->Server,
  1215. PromoteArgs->DnsDomainName,
  1216. LocalMachineAccountName,
  1217. FindOptions,
  1218. UF_WORKSTATION_TRUST_ACCOUNT |
  1219. UF_SERVER_TRUST_ACCOUNT,
  1220. &DomainControllerInfo );
  1221. if ( ERROR_SUCCESS != WinError ) {
  1222. DsRolepLogPrint(( DEB_ERROR, "Failed to get domain controller for account %ws (%d)\n", LocalMachineAccountName, WinError ));
  1223. DSROLEP_FAIL1( WinError, DSROLERES_FIND_DC, PromoteArgs->DnsDomainName );
  1224. goto PromoteUndo;
  1225. }
  1226. //
  1227. // Determine source server
  1228. //
  1229. if ( NULL == PromoteArgs->Server ) {
  1230. //
  1231. // No server was passed -- use the result of the dsgetdc
  1232. //
  1233. ReplicaServer = DomainControllerInfo->DomainControllerName;
  1234. } else {
  1235. ReplicaServer = PromoteArgs->Server;
  1236. if ( !DnsNameCompare_W(*(PromoteArgs->Server)==L'\\'?(PromoteArgs->Server)+2:PromoteArgs->Server,
  1237. *(DomainControllerInfo->DomainControllerName)==L'\\'?(DomainControllerInfo->DomainControllerName)+2:DomainControllerInfo->DomainControllerName ) ) {
  1238. WinError = ERROR_DS_UNWILLING_TO_PERFORM;
  1239. DsRolepLogPrint(( DEB_ERROR, "DsGetDcForAccount Failed to get the requested domain controller %ws for account %ws (%d)\n",
  1240. PromoteArgs->Server,
  1241. LocalMachineAccountName,
  1242. WinError));
  1243. DSROLEP_FAIL3( WinError,
  1244. DSROLERES_FAILED_FIND_REQUESTED_DC,
  1245. PromoteArgs->Server,
  1246. LocalMachineAccountName,
  1247. DomainControllerInfo->DomainControllerName );
  1248. goto PromoteUndo;
  1249. }
  1250. }
  1251. //
  1252. // Determine destination site
  1253. //
  1254. // Site need to be chosen by the following rules
  1255. // 1) If a site is given new DC should be placed into that site.
  1256. // 2) If no site is given new DC should end up in site base on IP.
  1257. // 3) If no site and subnet not defined but replica partner is given then new DC should end up in replica partner's site
  1258. // 4) If have none of the above then site is random.
  1259. //
  1260. if ( PromoteArgs->SiteName == NULL ) {
  1261. if ( PromoteArgs->Server == NULL ) {
  1262. PromoteArgs->SiteName = DomainControllerInfo->ClientSiteName;
  1263. } else {
  1264. WinError = DsGetDcName( NULL,
  1265. PromoteArgs->DnsDomainName,
  1266. NULL,
  1267. NULL,
  1268. FindOptions,
  1269. &ClientSiteInfo );
  1270. if ( ERROR_SUCCESS != WinError ) {
  1271. DsRolepLogPrint(( DEB_ERROR, "Failed to find site for %ws (%d)\n", LocalMachineAccountName, WinError ));
  1272. DSROLEP_FAIL1( WinError, DSROLERES_FAILED_FIND_SITE, LocalMachineAccountName );
  1273. goto PromoteUndo;
  1274. }
  1275. PromoteArgs->SiteName = ClientSiteInfo->ClientSiteName;
  1276. }
  1277. if ( PromoteArgs->SiteName == NULL ) {
  1278. if ( ClientSiteInfo ) {
  1279. NetApiBufferFree(ClientSiteInfo);
  1280. ClientSiteInfo = NULL;
  1281. }
  1282. PromoteArgs->SiteName = DomainControllerInfo->DcSiteName;
  1283. }
  1284. }
  1285. DSROLEP_CURRENT_OP2( DSROLEEVT_FOUND_SITE,
  1286. PromoteArgs->SiteName,
  1287. ReplicaServer );
  1288. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1289. if (!IPCConnection) {
  1290. WinError = DsRolepTimeSyncAndManageIPCConnect((PVOID)PromoteArgs,
  1291. ReplicaServer);
  1292. if ( WinError != ERROR_SUCCESS ) {
  1293. goto PromoteUndo;
  1294. }
  1295. IPCConnection = TRUE;
  1296. }
  1297. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1298. //
  1299. // Stop netlogon
  1300. //
  1301. DSROLEP_CURRENT_OP1( DSROLEEVT_STOP_SERVICE, SERVICE_NETLOGON );
  1302. WinError = DsRolepStopNetlogon( &RestartNetlogon );
  1303. if ( ERROR_SUCCESS != WinError ) {
  1304. DsRolepLogPrint(( DEB_ERROR, "Failed to stop NETLOGON (%d)\n", WinError ));
  1305. goto PromoteUndo;
  1306. }
  1307. DsRolepLogPrint(( DEB_TRACE, "Stopped NETLOGON\n" ));
  1308. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1309. //
  1310. // Create the system volume information
  1311. //
  1312. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  1313. WinError = DsRolepCreateSysVolPath( PromoteArgs->SysVolRootPath,
  1314. PromoteArgs->DnsDomainName,
  1315. ReplicaServer,
  1316. PromoteArgs->Account,
  1317. PromoteArgs->Password.Buffer,
  1318. PromoteArgs->SiteName,
  1319. FALSE );
  1320. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  1321. if ( ERROR_SUCCESS != WinError ) {
  1322. DsRolepLogPrint(( DEB_ERROR, "Failed to create system volume path (%d)\n", WinError ));
  1323. goto PromoteUndo;
  1324. }
  1325. DsRolepLogPrint(( DEB_TRACE, "Created system volume path\n" ));
  1326. SysVolCreated = TRUE;
  1327. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1328. //
  1329. // Setup the Ds
  1330. //
  1331. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->DomainAdminPassword );
  1332. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  1333. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->SafeModePassword );
  1334. WinError = DsRolepInstallDs( PromoteArgs->DnsDomainName,
  1335. PromoteArgs->FlatDomainName,
  1336. NULL, // DnsTreeRoot not used for replica installs
  1337. PromoteArgs->SiteName,
  1338. PromoteArgs->DsDatabasePath,
  1339. PromoteArgs->DsLogPath,
  1340. PromoteArgs->pIfmSystemInfo,
  1341. PromoteArgs->SysVolRootPath,
  1342. &(PromoteArgs->Bootkey),
  1343. PromoteArgs->DomainAdminPassword.Buffer,
  1344. PromoteArgs->Parent,
  1345. ReplicaServer,
  1346. PromoteArgs->Account,
  1347. PromoteArgs->Password.Buffer,
  1348. PromoteArgs->SafeModePassword.Buffer,
  1349. PromoteArgs->DnsDomainName,
  1350. PromoteArgs->Options,
  1351. TRUE,
  1352. PromoteArgs->ImpersonateToken,
  1353. &InstalledSite,
  1354. &DomainGuid,
  1355. &NewDomainSid );
  1356. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  1357. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->DomainAdminPassword );
  1358. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->SafeModePassword );
  1359. if ( ERROR_SUCCESS != WinError ) {
  1360. DsRolepLogPrint(( DEB_ERROR, "Failed to install to Directory Service (%d)\n", WinError ));
  1361. goto PromoteUndo;
  1362. }
  1363. DsRunning = TRUE;
  1364. DsInstalled = TRUE;
  1365. DsRolepLogPrint(( DEB_TRACE, "Installed Directory Service\n" ));
  1366. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1367. //
  1368. // Set the lsa domain information to reflect the new security database
  1369. // that was brought in. The Set below does not set the DnsDomainInformation,
  1370. // since the flat name is not yet known. The DnsDomainInformation gets
  1371. // set by the DsRolepSetLsaInformationForReplica call following.
  1372. //
  1373. WinError = DsRolepBackupDomainPolicyInfo( NULL, &BackupDomainPolicyInfo );
  1374. if ( ERROR_SUCCESS != WinError ) {
  1375. DsRolepLogPrint(( DEB_ERROR, "Failed to make backup of LSA policy (%d)\n", WinError ));
  1376. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_READ_LOCAL );
  1377. goto PromoteUndo;
  1378. }
  1379. WinError = DsRolepSetLsaDomainPolicyInfo( PromoteArgs->DnsDomainName,
  1380. PromoteArgs->FlatDomainName,
  1381. NULL,
  1382. &DomainGuid,
  1383. NewDomainSid,
  1384. NTDS_INSTALL_REPLICA,
  1385. &BackupDomainPolicyInfo );
  1386. if ( ERROR_SUCCESS != WinError ) {
  1387. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_WRITE_LOCAL );
  1388. goto PromoteUndo;
  1389. }
  1390. DomainPolicyInfoChanged = TRUE;
  1391. DsRolepLogPrint(( DEB_TRACE, "Wrote the LSA policy information for the local machine\n" ));
  1392. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1393. //
  1394. // This extra call is necessary to get the dns tree information
  1395. //
  1396. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  1397. WinError = DsRolepSetLsaInformationForReplica( PromoteArgs->ImpersonateToken,
  1398. ReplicaServer,
  1399. PromoteArgs->Account,
  1400. PromoteArgs->Password.Buffer );
  1401. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  1402. if ( ERROR_SUCCESS != WinError ) {
  1403. DSROLEP_FAIL1( WinError, DSROLERES_POLICY_READ_REMOTE, ReplicaServer );
  1404. goto PromoteUndo;
  1405. }
  1406. DsRolepLogPrint(( DEB_TRACE, "Read the LSA policy information from %ws\n",
  1407. ReplicaServer ));
  1408. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1409. //
  1410. // Configure the services for a domain controller
  1411. //
  1412. WinError = DsRolepConfigureDomainControllerServices( DSROLEP_SERVICES_ON );
  1413. if ( ERROR_SUCCESS != WinError ) {
  1414. DsRolepLogPrint(( DEB_ERROR, "Failed to configure domain controller services (%d)\n", WinError ));
  1415. goto PromoteUndo;
  1416. }
  1417. DomainControllerServicesChanged = TRUE;
  1418. DsRolepLogPrint(( DEB_TRACE, "Configured domain controller services\n" ));
  1419. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, PromoteUndo );
  1420. //
  1421. // Set the computers Dns domain name
  1422. //
  1423. DSROLEP_CURRENT_OP1( DSROLEEVT_SET_COMPUTER_DNS, PromoteArgs->DnsDomainName );
  1424. WinError = NetpSetDnsComputerNameAsRequired( PromoteArgs->DnsDomainName );
  1425. if ( ERROR_SUCCESS != WinError ) {
  1426. DsRolepLogOnFailure( WinError,
  1427. DsRolepLogPrint(( DEB_TRACE,
  1428. "NetpSetDnsComputerNameAsRequired to %ws failed with %lu\n",
  1429. PromoteArgs->DnsDomainName,
  1430. WinError )) );
  1431. DSROLEP_FAIL1( WinError, DSROLERES_SET_COMPUTER_DNS, PromoteArgs->DnsDomainName );
  1432. goto PromoteUndo;
  1433. }
  1434. DsRolepLogPrint(( DEB_TRACE, "Set the computer's Dns domain name to %ws.\n",
  1435. PromoteArgs->DnsDomainName ));
  1436. //
  1437. // Complete the sysvol replication
  1438. //
  1439. if ( SysVolCreated ) {
  1440. WinError = DsRolepFinishSysVolPropagation( TRUE, TRUE );
  1441. if ( ERROR_SUCCESS != WinError ) {
  1442. DsRolepLogPrint(( DEB_ERROR, "Failed to complete system volume replication (%d)\n", WinError ));
  1443. goto PromoteUndo;
  1444. }
  1445. DsRolepLogPrint(( DEB_TRACE, "Completed system volume replication\n" ));
  1446. }
  1447. //
  1448. // Set the machine role
  1449. //
  1450. WinError = DsRolepSetProductType( DSROLEP_MT_MEMBER );
  1451. if ( ERROR_SUCCESS != WinError ) {
  1452. DsRolepLogPrint(( DEB_ERROR, "Failed to set the product type (%d)\n", WinError ));
  1453. goto PromoteUndo;
  1454. }
  1455. DsRolepLogPrint(( DEB_TRACE, "Set the product type\n" ));
  1456. ProductTypeChanged = TRUE;
  1457. //
  1458. // Save off the new site name
  1459. //
  1460. WinError = DsRolepSetOperationHandleSiteName( InstalledSite );
  1461. if ( ERROR_SUCCESS != WinError ) {
  1462. DsRolepLogPrint(( DEB_ERROR, "Failed to set the operation handle(%d)\n", WinError ));
  1463. goto PromoteUndo;
  1464. }
  1465. //
  1466. // If we update it, NULL out the local parameter so we don't attempt to delete it
  1467. //
  1468. InstalledSite = NULL;
  1469. //
  1470. // Next, set the sysvol path for netlogon
  1471. //
  1472. WinError = DsRolepSetNetlogonSysVolPath( PromoteArgs->SysVolRootPath,
  1473. PromoteArgs->DnsDomainName,
  1474. FALSE,
  1475. NULL );
  1476. if ( ERROR_SUCCESS != WinError ) {
  1477. DsRolepLogPrint(( DEB_ERROR, "Failed to set the system volume path for NETLOGON (%d)\n", WinError ));
  1478. goto PromoteUndo;
  1479. }
  1480. DsRolepLogPrint(( DEB_TRACE, "Set the system volume path for NETLOGON\n" ));
  1481. //
  1482. // Finally, set the security on the dc files
  1483. //
  1484. WinError = DsRolepSetDcSecurity( PromoteArgs->ImpersonateToken,
  1485. PromoteArgs->SysVolRootPath,
  1486. PromoteArgs->DsDatabasePath,
  1487. PromoteArgs->DsLogPath,
  1488. ( BOOLEAN )FLAG_ON( PromoteArgs->Options,
  1489. DSROLE_DC_DOWNLEVEL_UPGRADE ),
  1490. TRUE );
  1491. if ( ERROR_SUCCESS != WinError ) {
  1492. DsRolepLogPrint(( DEB_ERROR, "Failed to set security for the domain controller (%d)\n", WinError ));
  1493. goto PromoteUndo;
  1494. }
  1495. DsRolepLogPrint(( DEB_TRACE, "Set security for the domain controller\n" ));
  1496. //
  1497. // We have done all operations for the promotion; now continue replicating
  1498. // ds information until done, or cancelled
  1499. //
  1500. DsRolepLogPrint(( DEB_TRACE, "Replicating non critical information\n" ));
  1501. DsRolepSetCriticalOperationsDone();
  1502. if ( !FLAG_ON( PromoteArgs->Options, DSROLE_DC_CRITICAL_REPLICATION_ONLY ) ) {
  1503. //in the Install From Media case we do not want to do a full sync of the
  1504. //Non-Critical objects
  1505. if ((PromoteArgs->pIfmSystemInfo != NULL)) {
  1506. WinError = (*DsrNtdsInstallReplicateFull) ( DsRolepStringUpdateCallback, PromoteArgs->ImpersonateToken, NTDS_IFM_PROMOTION );
  1507. } else {
  1508. WinError = (*DsrNtdsInstallReplicateFull) ( DsRolepStringUpdateCallback, PromoteArgs->ImpersonateToken, 0 );
  1509. }
  1510. if ( WinError != ERROR_SUCCESS ) {
  1511. //
  1512. // Error code doesn't matter, but we'll log it anyway
  1513. //
  1514. DsRolepLogOnFailure( WinError,
  1515. DsRolepLogPrint(( DEB_WARN,
  1516. "Non critical replication returned %lu\n", WinError )) );
  1517. if (ERROR_SUCCESS == WinError) {
  1518. DsRolepLogPrint(( DEB_TRACE, "Replicating non critical information (Complete)\n" ));
  1519. }
  1520. if ( ERROR_SUCCESS != WinError ) {
  1521. DSROLEP_SET_NON_CRIT_REPL_ERROR();
  1522. }
  1523. WinError = ERROR_SUCCESS;
  1524. }
  1525. } else {
  1526. DsRolepLogPrint(( DEB_TRACE, "User specified to not replicate non-critical data\n" ));
  1527. }
  1528. //
  1529. // Indicate that we are no longer doing upgrades, if applicable
  1530. //
  1531. if ( FLAG_ON( PromoteArgs->Options, DSROLE_DC_DOWNLEVEL_UPGRADE ) ) {
  1532. WinError = DsRolepDeleteUpgradeInfo();
  1533. DsRolepLogOnFailure( WinError,
  1534. DsRolepLogPrint(( DEB_WARN,
  1535. "Failed to remove upgrade information (%d)\n",
  1536. WinError )) );
  1537. // This error isn't interesting to propogate
  1538. WinError = ERROR_SUCCESS;
  1539. }
  1540. //
  1541. // Remove any old netlogon stuff if we got that far
  1542. //
  1543. WinError = DsRolepCleanupOldNetlogonInformation();
  1544. if ( (FLAG_ON( PromoteArgs->Options, DSROLE_DC_DOWNLEVEL_UPGRADE )) && ERROR_SUCCESS != WinError ) {
  1545. if (ERROR_SUCCESS == WinError) {
  1546. DsRolepLogPrint(( DEB_TRACE, "Removed any old netlogon information\n" ));
  1547. }
  1548. DsRolepLogOnFailure( WinError,
  1549. DsRolepLogPrint(( DEB_WARN,
  1550. "Failed to clean up old netlogon information (%d)\n",
  1551. WinError )) );
  1552. }
  1553. WinError = ERROR_SUCCESS;
  1554. //
  1555. // Set the default logon domain to the current domain name
  1556. //
  1557. //
  1558. // We'll have to get it from the backed up policy information, since it isn't actually
  1559. // passed in
  1560. //
  1561. WinError = DsRolepSetLogonDomain(
  1562. ( PWSTR )BackupDomainPolicyInfo.DnsDomainInfo->Name.Buffer,
  1563. FALSE );
  1564. if ( ERROR_SUCCESS != WinError ) {
  1565. PWCHAR bufDnsDomainInfo = NULL;
  1566. bufDnsDomainInfo = (WCHAR*)malloc(BackupDomainPolicyInfo.DnsDomainInfo->Name.Length+sizeof(WCHAR));
  1567. if (bufDnsDomainInfo) {
  1568. CopyMemory(bufDnsDomainInfo,
  1569. BackupDomainPolicyInfo.DnsDomainInfo->Name.Buffer,
  1570. BackupDomainPolicyInfo.DnsDomainInfo->Name.Length);
  1571. bufDnsDomainInfo[BackupDomainPolicyInfo.DnsDomainInfo->Name.Length/sizeof(WCHAR)] = L'\0';
  1572. DsRolepLogOnFailure( WinError,
  1573. DsRolepLogPrint(( DEB_WARN,
  1574. "Failed to set default logon domain to %ws (%d)\n",
  1575. bufDnsDomainInfo,
  1576. WinError )) );
  1577. if (ERROR_SUCCESS == WinError) {
  1578. DsRolepLogPrint(( DEB_TRACE, "Set default logon domain to %ws\n",
  1579. bufDnsDomainInfo ));
  1580. }
  1581. free(bufDnsDomainInfo);
  1582. }
  1583. //
  1584. // This is not worth failing for
  1585. //
  1586. WinError = ERROR_SUCCESS;
  1587. }
  1588. //
  1589. // Stop the ds
  1590. //
  1591. DsRolepStopDs( DsRunning );
  1592. DsRunning = FALSE;
  1593. DsRolepLogPrint(( DEB_TRACE, "Stopped the DS\n" ));
  1594. //
  1595. // Notify the time server we have completed the promotion
  1596. //
  1597. (*DsrW32TimeDcPromo)( W32TIME_PROMOTE );
  1598. //
  1599. // Set Netlogon registry key during DCPromo to ensure that kerberos is talking
  1600. // to a DC w/ new User AccountControl flag
  1601. //
  1602. IgnoreError = NetpStoreIntialDcRecord(DomainControllerInfo);
  1603. if ( IgnoreError != ERROR_SUCCESS ) {
  1604. DsRolepLogPrint(( DEB_WARN,
  1605. "Failed to set Netlogon registry key during DCPromo %ws\r\n",
  1606. IgnoreError ));
  1607. }
  1608. //
  1609. // At this point we have succeeded the promotion
  1610. //
  1611. ASSERT( ERROR_SUCCESS == WinError );
  1612. PromoteExit:
  1613. //
  1614. // Released acquired resources
  1615. //
  1616. if ( IPCConnection ) {
  1617. RtlRunDecodeUnicodeString( PromoteArgs->Decode, &PromoteArgs->Password );
  1618. IgnoreError = ImpNetpManageIPCConnect( PromoteArgs->ImpersonateToken,
  1619. ReplicaServer,
  1620. PromoteArgs->Account,
  1621. PromoteArgs->Password.Buffer,
  1622. (NETSETUPP_DISCONNECT_IPC | NETSETUPP_USE_LOTS_FORCE ) );
  1623. RtlRunEncodeUnicodeString( &PromoteArgs->Decode, &PromoteArgs->Password );
  1624. if ( IgnoreError != ERROR_SUCCESS ) {
  1625. DsRolepLogPrint(( DEB_ERROR,
  1626. "Failed to destroy the session with %ws: 0x%lx\n", ReplicaServer,
  1627. IgnoreError ));
  1628. }
  1629. IPCConnection = FALSE;
  1630. }
  1631. if ( DomainControllerInfo != NULL ) {
  1632. if ( PromoteArgs->SiteName == DomainControllerInfo->ClientSiteName ||
  1633. PromoteArgs->SiteName == DomainControllerInfo->DcSiteName ) {
  1634. PromoteArgs->SiteName = NULL;
  1635. }
  1636. NetApiBufferFree( DomainControllerInfo );
  1637. }
  1638. if ( ClientSiteInfo != NULL ) {
  1639. if ( PromoteArgs->SiteName == ClientSiteInfo->ClientSiteName ||
  1640. PromoteArgs->SiteName == ClientSiteInfo->DcSiteName ) {
  1641. PromoteArgs->SiteName = NULL;
  1642. }
  1643. NetApiBufferFree( ClientSiteInfo );
  1644. }
  1645. RtlFreeHeap( RtlProcessHeap(), 0, InstalledSite );
  1646. RtlFreeHeap( RtlProcessHeap(), 0, NewDomainSid );
  1647. DsRolepFreeDomainPolicyInfo(&BackupDomainPolicyInfo);
  1648. //
  1649. // Reset our operation handle
  1650. //
  1651. DsRolepSetOperationDone( DSROLEP_OP_PROMOTION, WinError );
  1652. DsRolepFreeArgumentBlock( &ArgumentBlock, TRUE );
  1653. ExitThread( WinError );
  1654. return( WinError );
  1655. PromoteUndo:
  1656. //
  1657. // Something must have failed to have gotten us here
  1658. //
  1659. ASSERT( ERROR_SUCCESS != WinError );
  1660. if ( ProductTypeChanged ) {
  1661. IgnoreError = DsRolepSetProductType( DSROLEP_MT_STANDALONE );
  1662. DsRolepLogOnFailure( IgnoreError,
  1663. DsRolepLogPrint(( DEB_WARN,
  1664. "Failed to rollback product type (%d)\n",
  1665. IgnoreError )) );
  1666. ProductTypeChanged = FALSE;
  1667. }
  1668. if ( DomainControllerServicesChanged ) {
  1669. IgnoreError = DsRolepConfigureDomainControllerServices( DSROLEP_SERVICES_REVERT );
  1670. DsRolepLogOnFailure( IgnoreError,
  1671. DsRolepLogPrint(( DEB_WARN,
  1672. "Failed to rollback domain controller services configuration (%d)\n",
  1673. IgnoreError )) );
  1674. DomainControllerServicesChanged = FALSE;
  1675. }
  1676. if ( DomainPolicyInfoChanged ) {
  1677. IgnoreError = DsRolepRestoreDomainPolicyInfo(&BackupDomainPolicyInfo);
  1678. DsRolepLogOnFailure( IgnoreError,
  1679. DsRolepLogPrint(( DEB_WARN,
  1680. "Failed to restore domain policy information (%d)\n",
  1681. IgnoreError )) );
  1682. DomainPolicyInfoChanged = FALSE;
  1683. }
  1684. if ( DsRunning ) {
  1685. IgnoreError = DsRolepStopDs( DsRunning );
  1686. DsRolepLogOnFailure( IgnoreError,
  1687. DsRolepLogPrint(( DEB_WARN,
  1688. "Failed to stop the directory service (%d)\n",
  1689. IgnoreError )) );
  1690. DsRunning = FALSE;
  1691. }
  1692. if ( DsInstalled ) {
  1693. IgnoreError = DsRolepUninstallDs( );
  1694. DsRolepLogOnFailure( IgnoreError,
  1695. DsRolepLogPrint(( DEB_WARN,
  1696. "Failed to undo the directory service installation (%d)\n",
  1697. IgnoreError )) );
  1698. DsInstalled = FALSE;
  1699. }
  1700. if ( SysVolCreated ) {
  1701. IgnoreError = DsRolepFinishSysVolPropagation( FALSE, TRUE );
  1702. DsRolepLogOnFailure( IgnoreError,
  1703. DsRolepLogPrint(( DEB_WARN,
  1704. "Failed to abort system volume installation (%d)\n",
  1705. IgnoreError )) );
  1706. IgnoreError = DsRolepRemoveSysVolPath( PromoteArgs->SysVolRootPath,
  1707. PromoteArgs->DnsDomainName,
  1708. &DomainGuid );
  1709. DsRolepLogOnFailure( IgnoreError,
  1710. DsRolepLogPrint(( DEB_WARN,
  1711. "Failed to remove system volume path (%d)\n",
  1712. IgnoreError )) );
  1713. SysVolCreated = FALSE;
  1714. }
  1715. if ( RestartNetlogon ) {
  1716. IgnoreError = DsRolepStartNetlogon();
  1717. DsRolepLogOnFailure( IgnoreError,
  1718. DsRolepLogPrint(( DEB_WARN,
  1719. "Failed to restart NETLOGON (%d)\n",
  1720. IgnoreError )) );
  1721. RestartNetlogon = FALSE;
  1722. }
  1723. //
  1724. // That's it -- terminate the operation
  1725. //
  1726. ASSERT( ERROR_SUCCESS != WinError );
  1727. goto PromoteExit;
  1728. }
  1729. DWORD
  1730. DsRolepThreadDemote(
  1731. IN PVOID ArgumentBlock
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. This function actually "demotes" a dc to standalone or member server. This is
  1736. accomplished by:
  1737. Uninstalling the Ds
  1738. Configuring the KDC
  1739. Changing the product type
  1740. Removing the system volume tree
  1741. Required is the new server role
  1742. Arguments:
  1743. ArgumentBlock - Block of arguments appropriate for the operation
  1744. Returns:
  1745. ERROR_SUCCESS - Success
  1746. ERROR_NO_SUCH_DOMAIN - The local domain information could not be located
  1747. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  1748. ERROR_DS_CANT_ON_NON_LEAF - The domain is not a leaf domain
  1749. --*/
  1750. {
  1751. DWORD WinError = ERROR_SUCCESS, IgnoreError;
  1752. NET_API_STATUS NetStatus = ERROR_SUCCESS;
  1753. PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
  1754. PDSROLEP_OPERATION_DEMOTE_ARGS DemoteArgs = ( PDSROLEP_OPERATION_DEMOTE_ARGS )ArgumentBlock;
  1755. DSROLEP_DOMAIN_POLICY_INFO BackupDomainPolicyInfo;
  1756. PPOLICY_DNS_DOMAIN_INFO DnsDomainInfo = NULL;
  1757. HANDLE Policy = NULL;
  1758. NTSTATUS Status;
  1759. PWSTR ParentDomainName = NULL, CurrentDomain = NULL, SupportDc = NULL;
  1760. PWSTR SupportDomain = NULL;
  1761. OBJECT_ATTRIBUTES ObjectAttributes;
  1762. BOOLEAN fNoNetworkOperations = FALSE;
  1763. ULONG ServicesOffFlags = DSROLEP_SERVICES_OFF | DSROLEP_SERVICES_STOP;
  1764. ULONG ServicesOnFlags = DSROLEP_SERVICES_REVERT;
  1765. PNTDS_DNS_RR_INFO pDnsRRInfo = NULL;
  1766. ULONG Flags = 0;
  1767. PSEC_WINNT_AUTH_IDENTITY Credentials = NULL;
  1768. ULONG FindOptions = DS_DIRECTORY_SERVICE_REQUIRED |
  1769. DS_WRITABLE_REQUIRED |
  1770. DS_FORCE_REDISCOVERY |
  1771. DS_AVOID_SELF |
  1772. DS_RETURN_DNS_NAME;
  1773. //
  1774. // BOOLEAN's to maintain state
  1775. //
  1776. // N.B. The order of these booleans is the order in which they
  1777. // are changed -- please maintain order and make sure that
  1778. // the DemoteUndo section undoes them in the reverse order
  1779. //
  1780. BOOLEAN IPCConnection = FALSE; // resource -- release on exit
  1781. BOOLEAN DsPrepareDemote = FALSE;
  1782. BOOLEAN FrsDemote = FALSE;
  1783. BOOLEAN NotifiedNetlogonToDeregister = FALSE;
  1784. BOOLEAN RestartNetlogon = FALSE;
  1785. BOOLEAN DomainControllerServicesChanged = FALSE;
  1786. BOOLEAN DomainServicesChanged = FALSE;
  1787. BOOLEAN Unrollable = FALSE; // at this point, don't
  1788. // try to rollback
  1789. //
  1790. // Set our event to indicate we're starting
  1791. //
  1792. NtSetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  1793. //
  1794. // If This is a Forced Demotion then we will not do any network
  1795. // operations
  1796. //
  1797. if ( FLAG_ON( DemoteArgs->Options, DSROLE_DC_FORCE_DEMOTE ) ) {
  1798. DsRolepLogPrint(( DEB_TRACE,
  1799. "Performing Forced Demotion"));
  1800. fNoNetworkOperations = TRUE;
  1801. //We also do not want to fail if we couldn't configure services
  1802. ServicesOffFlags |= DSROLEP_SERVICES_IGNORE_ERRORS;
  1803. }
  1804. //
  1805. // Get the current domain information, potentially the parent Domain and see if
  1806. // we are valid to be demoted
  1807. //
  1808. DSROLEP_CURRENT_OP0( DSROLEEVT_LOCAL_POLICY );
  1809. RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  1810. Status = LsaOpenPolicy( NULL,
  1811. &ObjectAttributes,
  1812. POLICY_VIEW_LOCAL_INFORMATION,
  1813. &Policy );
  1814. if ( NT_SUCCESS( Status ) ) {
  1815. Status = LsaQueryInformationPolicy( Policy,
  1816. PolicyDnsDomainInformation,
  1817. &DnsDomainInfo );
  1818. }
  1819. if ( !NT_SUCCESS( Status ) ) {
  1820. WinError = RtlNtStatusToDosError( Status );
  1821. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_READ_LOCAL );
  1822. goto DemoteUndo;
  1823. }
  1824. if ( DemoteArgs->DomainName == NULL ) {
  1825. CurrentDomain = DnsDomainInfo->DnsDomainName.Buffer;
  1826. } else {
  1827. //
  1828. // Strip the trailing '.' from the Dns name if we happen to have an absolute name
  1829. //
  1830. DSROLEP_MAKE_DNS_RELATIVE( DemoteArgs->DomainName );
  1831. CurrentDomain = DemoteArgs->DomainName;
  1832. }
  1833. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  1834. //
  1835. // Determine whether it is legal to demote this domain. Also, get the parent Dns domain name
  1836. //
  1837. if ( DemoteArgs->LastDcInDomain && !fNoNetworkOperations ) {
  1838. PLSAPR_FOREST_TRUST_INFO ForestTrustInfo = NULL;
  1839. PLSAPR_TREE_TRUST_INFO OwnEntry = NULL, ParentEntry = NULL;
  1840. Status = LsaIQueryForestTrustInfo( Policy,
  1841. &ForestTrustInfo );
  1842. WinError = RtlNtStatusToDosError( Status );
  1843. if ( WinError == ERROR_SUCCESS ) {
  1844. //
  1845. // Check the root
  1846. //
  1847. if ( RtlCompareUnicodeString(
  1848. ( PUNICODE_STRING )&ForestTrustInfo->RootTrust.DnsDomainName,
  1849. &DnsDomainInfo->DnsDomainName,
  1850. TRUE ) == 0 ) {
  1851. OwnEntry = &ForestTrustInfo->RootTrust;
  1852. ParentEntry = NULL;
  1853. } else {
  1854. //
  1855. // Find our own entry in the list and our parent...
  1856. //
  1857. DsRolepFindSelfAndParentInForest( ForestTrustInfo,
  1858. &ForestTrustInfo->RootTrust,
  1859. &DnsDomainInfo->DnsDomainName,
  1860. &ParentEntry,
  1861. &OwnEntry );
  1862. }
  1863. if ( OwnEntry == NULL ) {
  1864. WinError = ERROR_NO_SUCH_DOMAIN;
  1865. } else {
  1866. //
  1867. // If we have children, it's an error
  1868. //
  1869. if ( OwnEntry->Children != 0 ) {
  1870. WCHAR *BufOwnEntry = NULL;
  1871. DsRolepUnicodestringtowstr( BufOwnEntry, OwnEntry->DnsDomainName )
  1872. if (BufOwnEntry) {
  1873. DsRolepLogPrint(( DEB_TRACE,
  1874. "We ( %ws ) think we have %lu children\n",
  1875. BufOwnEntry,
  1876. OwnEntry->Children ));
  1877. free(BufOwnEntry);
  1878. } else {
  1879. DsRolepLogPrint(( DEB_TRACE,
  1880. "We think we have %lu children: Can display string ERROR_NOT_ENOUGH_MEMORY\n",
  1881. OwnEntry->Children ));
  1882. }
  1883. WinError = ERROR_DS_CANT_ON_NON_LEAF;
  1884. }
  1885. //
  1886. // Copy off our parent information
  1887. //
  1888. if ( WinError == ERROR_SUCCESS && ParentEntry != NULL ) {
  1889. WCHAR *BufOwnEntry = NULL;
  1890. DsRolepUnicodestringtowstr( BufOwnEntry, OwnEntry->DnsDomainName )
  1891. if (BufOwnEntry) {
  1892. DsRolepLogPrint((DEB_TRACE,
  1893. "Domain %ws is our parent parent\n",
  1894. BufOwnEntry));
  1895. free(BufOwnEntry);
  1896. } else {
  1897. DsRolepLogPrint(( DEB_TRACE,
  1898. "Domain (?) is our parent parent: Can display domain string ERROR_NOT_ENOUGH_MEMORY\n"));
  1899. }
  1900. ParentDomainName = RtlAllocateHeap(
  1901. RtlProcessHeap(), 0,
  1902. ParentEntry->DnsDomainName.Length + sizeof( WCHAR ) );
  1903. if ( ParentDomainName == NULL ) {
  1904. WinError = ERROR_NOT_ENOUGH_MEMORY;
  1905. } else {
  1906. RtlCopyMemory( ParentDomainName,
  1907. ParentEntry->DnsDomainName.Buffer,
  1908. ParentEntry->DnsDomainName.Length );
  1909. ParentDomainName[
  1910. ParentEntry->DnsDomainName.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
  1911. }
  1912. }
  1913. }
  1914. }
  1915. LsaIFreeForestTrustInfo( ForestTrustInfo );
  1916. if ( ERROR_SUCCESS != WinError ) {
  1917. DSROLEP_FAIL1( WinError, DSROLERES_LEAF_DOMAIN, CurrentDomain );
  1918. goto DemoteUndo;
  1919. }
  1920. }
  1921. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  1922. //
  1923. // Locate a Dc to help with the demotion
  1924. //
  1925. if ( !fNoNetworkOperations ) {
  1926. if ( DemoteArgs->LastDcInDomain ) {
  1927. SupportDomain = ParentDomainName;
  1928. } else {
  1929. SupportDomain = CurrentDomain;
  1930. }
  1931. }
  1932. //
  1933. // If this is the last domain in the enterprise, there will be no
  1934. // parent domain and possibly no replicas to assist.
  1935. //
  1936. // Note: netlogon is still running, so use the avoid self flag
  1937. //
  1938. if ( SupportDomain ) {
  1939. DSROLEP_CURRENT_OP1( DSROLEEVT_SEARCH_DC, SupportDomain );
  1940. if ( !DemoteArgs->LastDcInDomain )
  1941. {
  1942. //
  1943. // Demoting a replica - find someone with our machine account
  1944. //
  1945. WCHAR LocalMachineAccountName[ MAX_COMPUTERNAME_LENGTH + 2 ];
  1946. ULONG Length = sizeof(LocalMachineAccountName) / sizeof(LocalMachineAccountName[0]);
  1947. //
  1948. // Get the account name
  1949. //
  1950. if ( GetComputerName( LocalMachineAccountName, &Length ) == FALSE ) {
  1951. WinError = GetLastError();
  1952. DsRolepLogPrint(( DEB_ERROR, "Failed to get computer name (%d)\n", WinError ));
  1953. goto DemoteUndo;
  1954. } else {
  1955. wcscat( LocalMachineAccountName, L"$" );
  1956. WinError = DsRolepDsGetDcForAccount( NULL,
  1957. SupportDomain,
  1958. LocalMachineAccountName,
  1959. FindOptions,
  1960. UF_WORKSTATION_TRUST_ACCOUNT |
  1961. UF_SERVER_TRUST_ACCOUNT,
  1962. &DomainControllerInfo );
  1963. }
  1964. } else {
  1965. WinError = DsGetDcName( NULL, SupportDomain, NULL, NULL,
  1966. FindOptions,
  1967. &DomainControllerInfo );
  1968. }
  1969. if ( ERROR_SUCCESS != WinError ) {
  1970. DsRolepLogPrint(( DEB_ERROR,
  1971. "Failed to find a domain controller for %ws: %lu\n",
  1972. SupportDomain, WinError ));
  1973. DSROLEP_FAIL1( WinError, DSROLERES_FIND_DC, SupportDomain );
  1974. goto DemoteUndo;
  1975. }
  1976. SupportDc = DomainControllerInfo->DomainControllerName;
  1977. if ( *SupportDc == L'\\' ) {
  1978. SupportDc += 2;
  1979. }
  1980. DsRolepLogPrint(( DEB_TRACE_DS, "Support Dc in %ws is %ws\n",
  1981. SupportDomain,
  1982. SupportDc ));
  1983. DSROLEP_CURRENT_OP2( DSROLEEVT_FOUND_DC,
  1984. SupportDc,
  1985. SupportDomain );
  1986. }
  1987. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  1988. //
  1989. // Attempt to establish a RDR session with our support DC
  1990. // if necessary
  1991. //
  1992. if ( SupportDc ) {
  1993. //
  1994. // Impersonate to get logon id of caller
  1995. //
  1996. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  1997. WinError = ImpNetpManageIPCConnect( DemoteArgs->ImpersonateToken,
  1998. SupportDc,
  1999. DemoteArgs->Account,
  2000. DemoteArgs->Password.Buffer,
  2001. NETSETUPP_CONNECT_IPC );
  2002. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2003. if ( ERROR_SUCCESS != WinError ) {
  2004. DSROLEP_FAIL1( WinError, DSROLERES_NET_USE, SupportDc );
  2005. DsRolepLogPrint(( DEB_ERROR,
  2006. "Failed to establish the session with %ws: 0x%lx\n", SupportDc,
  2007. WinError ));
  2008. goto DemoteUndo;
  2009. }
  2010. IPCConnection = TRUE;
  2011. }
  2012. if ( DemoteArgs->LastDcInDomain ) {
  2013. Flags |= NTDS_LAST_DC_IN_DOMAIN;
  2014. }
  2015. Flags |= DsRolepDemoteFlagsToNtdsFlags( DemoteArgs->Options );
  2016. if ( !fNoNetworkOperations ) {
  2017. //
  2018. // Prepare the ds for demotion
  2019. //
  2020. DSROLE_GET_SETUP_FUNC( WinError, DsrNtdsPrepareForDemotion );
  2021. ASSERT( ERROR_SUCCESS == WinError );
  2022. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  2023. WinError = DsRolepCreateAuthIdentForCreds(DemoteArgs->Account,
  2024. DemoteArgs->Password.Buffer,
  2025. &Credentials);
  2026. if ( ERROR_SUCCESS == WinError ) {
  2027. DSROLEP_CURRENT_OP0( DSROLEEVT_PREPARE_DEMOTION );
  2028. //
  2029. // If this is a Force demotion. There is nothing to prepare.
  2030. //
  2031. WinError = ( *DsrNtdsPrepareForDemotion ) ( Flags,
  2032. SupportDc,
  2033. Credentials,
  2034. DsRolepStringUpdateCallback,
  2035. DsRolepStringErrorUpdateCallback,
  2036. DemoteArgs->ImpersonateToken,
  2037. DemoteArgs->cRemoveNCs,
  2038. DemoteArgs->pszRemoveNCs,
  2039. &pDnsRRInfo );
  2040. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2041. if ( ERROR_SUCCESS != WinError ) {
  2042. DsRolepLogPrint(( DEB_ERROR, "Failed to prepare the Directory Service for uninstallation (%d)\n", WinError ));
  2043. goto DemoteUndo;
  2044. }
  2045. DsPrepareDemote = TRUE;
  2046. } else {
  2047. DsRolepLogPrint(( DEB_ERROR, "Failed to create authentication credentials (%d)\n", WinError ));
  2048. goto DemoteUndo;
  2049. }
  2050. }
  2051. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2052. //
  2053. // Start the sysvol demotions
  2054. //
  2055. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  2056. WinError = ( *DsrNtFrsApi_PrepareForDemotionUsingCredW ) ( Credentials,
  2057. DemoteArgs->ImpersonateToken,
  2058. DsRolepStringErrorUpdateCallback );
  2059. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2060. if ( ERROR_SUCCESS != WinError ) {
  2061. DsRolepLogPrint(( DEB_ERROR, "Failed to get computer name (%d)\n", WinError ));
  2062. DSROLEP_FAIL0( WinError, DSROLERES_SYSVOL_DEMOTION );
  2063. goto DemoteUndo;
  2064. }
  2065. WinError = ( *DsrNtFrsApi_StartDemotionW )( CurrentDomain,
  2066. DsRolepStringErrorUpdateCallback );
  2067. if ( ERROR_SUCCESS != WinError ) {
  2068. DsRolepLogPrint(( DEB_ERROR,
  2069. "Failed to start system volume demotion on domain (%d)\n",
  2070. WinError ));
  2071. DSROLEP_FAIL0( WinError, DSROLERES_SYSVOL_DEMOTION );
  2072. goto DemoteUndo;
  2073. }
  2074. // At this point we have signalled one frs replica set to be demote so
  2075. // we must wait on it
  2076. FrsDemote = TRUE;
  2077. WinError = ( *DsrNtFrsApi_StartDemotionW )( L"ENTERPRISE",
  2078. DsRolepStringErrorUpdateCallback );
  2079. if ( WinError != ERROR_SUCCESS ) {
  2080. DsRolepLogPrint(( DEB_ERROR,
  2081. "Failed to start system volume demotion on enterprise (%d)\n",
  2082. WinError ));
  2083. DSROLEP_FAIL0( WinError, DSROLERES_SYSVOL_DEMOTION );
  2084. goto DemoteUndo;
  2085. }
  2086. DsRolepLogPrint(( DEB_TRACE,
  2087. "Started system volume demotion on enterprise\n" ));
  2088. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2089. //
  2090. // Note that if a failure occurs after we uninstall the Ds, than we will not attempt to
  2091. // reinstall it, since we don't have enough information to do so. In that case, the machine
  2092. // will be in a somewhat inconsistent state. However, some errors are acceptable:
  2093. //
  2094. // Failure to delete the trusted domain object - Continuable
  2095. // Stoping the KDC - Continuable
  2096. //
  2097. //
  2098. // Also, note that "uninstalling the DS" also sets the LSA account domain
  2099. // sid and the server role so no errors should be returned to the caller
  2100. // after uninstalling the DS. The machine will become the new role on the
  2101. // next reboot.
  2102. //
  2103. WinError = DsRolepBackupDomainPolicyInfo( NULL, &BackupDomainPolicyInfo );
  2104. if ( ERROR_SUCCESS != WinError ) {
  2105. DsRolepLogPrint(( DEB_ERROR,
  2106. "Failed to backup LSA domain policy (%d)\n",
  2107. WinError ));
  2108. DSROLEP_FAIL0( WinError, DSROLERES_POLICY_READ_LOCAL );
  2109. goto DemoteUndo;
  2110. }
  2111. DsRolepLogPrint(( DEB_TRACE,
  2112. "Read the LSA policy information from the local machine\n" ));
  2113. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2114. //
  2115. // Set netlogon we are demoting so it will deregister the DNS records
  2116. // This will be skiped if this is a Forced demotion since it is a
  2117. // networking operation.
  2118. //
  2119. if ( !fNoNetworkOperations ) {
  2120. Status = I_NetNotifyDsChange( NlDcDemotionInProgress );
  2121. if ( !NT_SUCCESS( Status ) ) {
  2122. WinError = RtlNtStatusToDosError( Status );
  2123. DsRolepLogPrint(( DEB_ERROR,
  2124. "Failed to tell NETLOGON to deregister records (%d)\n",
  2125. WinError ));
  2126. goto DemoteUndo;
  2127. }
  2128. DsRolepLogPrint(( DEB_TRACE,
  2129. "Informed NETLOGON to deregister records\n" ));
  2130. NotifiedNetlogonToDeregister = TRUE;
  2131. }
  2132. //
  2133. // Stop netlogon
  2134. //
  2135. WinError = DsRolepStopNetlogon( &RestartNetlogon );
  2136. if ( ERROR_SUCCESS != WinError ) {
  2137. DsRolepLogPrint(( DEB_ERROR,
  2138. "Failed to stop NETLOGON (%d)\n",
  2139. WinError ));
  2140. //We don't want to fail because we couldn't stop netlogon
  2141. //during a forced demotion
  2142. if ( !fNoNetworkOperations ) {
  2143. goto DemoteUndo;
  2144. }
  2145. //log an event that states that netlogon could not
  2146. //be stopped during the forced demotion.
  2147. SpmpReportEvent( TRUE,
  2148. EVENTLOG_WARNING_TYPE,
  2149. DSROLERES_FAILED_STOPPING_NETLOGON,
  2150. 0,
  2151. sizeof( ULONG ),
  2152. &WinError,
  2153. 0 );
  2154. DSROLEP_SET_NON_FATAL_ERROR( WinError );
  2155. WinError = ERROR_SUCCESS;
  2156. }
  2157. if ( RestartNetlogon ) {
  2158. DsRolepLogPrint(( DEB_TRACE,
  2159. "Stopped NETLOGON\n" ));
  2160. }
  2161. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2162. //
  2163. // Disable the domain controller services
  2164. //
  2165. WinError = DsRolepConfigureDomainControllerServices( ServicesOffFlags );
  2166. if ( ERROR_SUCCESS != WinError ) {
  2167. DsRolepLogPrint(( DEB_ERROR,
  2168. "Failed to configure domain controller services (%d)\n",
  2169. WinError ));
  2170. goto DemoteUndo;
  2171. }
  2172. DsRolepLogPrint(( DEB_TRACE,
  2173. "Configured domain controller services\n" ));
  2174. DomainControllerServicesChanged = TRUE;
  2175. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2176. //
  2177. // Disable the domain related services if necessary
  2178. //
  2179. if ( DemoteArgs->ServerRole == DsRoleServerStandalone ) {
  2180. WinError = DsRolepConfigureDomainServices( ServicesOffFlags );
  2181. if ( ERROR_SUCCESS != WinError ) {
  2182. DsRolepLogPrint(( DEB_ERROR,
  2183. "Failed to configure domain services (%d)\n",
  2184. WinError ));
  2185. goto DemoteUndo;
  2186. }
  2187. DsRolepLogPrint(( DEB_TRACE,
  2188. "Configured domain services\n" ));
  2189. DomainServicesChanged = TRUE;
  2190. }
  2191. DSROLEP_CHECK_FOR_CANCEL_EX( WinError, DemoteUndo );
  2192. //
  2193. // Remove the Ds
  2194. //
  2195. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  2196. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->AdminPassword );
  2197. WinError = DsRolepDemoteDs( CurrentDomain,
  2198. DemoteArgs->Account,
  2199. DemoteArgs->Password.Buffer,
  2200. DemoteArgs->AdminPassword.Buffer,
  2201. SupportDc,
  2202. SupportDomain,
  2203. DemoteArgs->ImpersonateToken,
  2204. DemoteArgs->LastDcInDomain,
  2205. DemoteArgs->cRemoveNCs,
  2206. DemoteArgs->pszRemoveNCs,
  2207. DemoteArgs->Options
  2208. );
  2209. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2210. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->AdminPassword );
  2211. if ( ERROR_SUCCESS != WinError ) {
  2212. DsRolepLogPrint(( DEB_ERROR,
  2213. "Failed to demote the directory service (%d)\n",
  2214. WinError ));
  2215. goto DemoteUndo;
  2216. }
  2217. DsRolepLogPrint(( DEB_TRACE, "This machine is no longer a domain controller\n" ));
  2218. //
  2219. // The operation cannot be cancelled at this point since the ds has
  2220. // been removed from the machine and from the enterprise
  2221. //
  2222. Unrollable = TRUE;
  2223. //
  2224. // Optionally remove the trust with the parent
  2225. //
  2226. if ( DemoteArgs->LastDcInDomain &&
  2227. ParentDomainName != NULL &&
  2228. !fNoNetworkOperations ) {
  2229. //
  2230. // Establish a session first -- should be a no-op since we already
  2231. // have a connection
  2232. //
  2233. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  2234. WinError = ImpNetpManageIPCConnect( DemoteArgs->ImpersonateToken,
  2235. SupportDc,
  2236. DemoteArgs->Account,
  2237. DemoteArgs->Password.Buffer,
  2238. NETSETUPP_CONNECT_IPC );
  2239. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2240. if ( WinError == ERROR_SUCCESS ) {
  2241. WinError = DsRolepDeleteParentTrustObject( DemoteArgs->ImpersonateToken,
  2242. SupportDc,
  2243. DnsDomainInfo );
  2244. if ( WinError != ERROR_SUCCESS ) {
  2245. DsRolepLogOnFailure( WinError,
  2246. DsRolepLogPrint(( DEB_WARN,
  2247. "Failed to delete the "
  2248. "trust on %ws: %lu\n",
  2249. SupportDc,
  2250. WinError )) );
  2251. if (ERROR_SUCCESS == WinError) {
  2252. DsRolepLogPrint(( DEB_TRACE,
  2253. "Deleted the trust on %ws\n",
  2254. SupportDc ));
  2255. }
  2256. }
  2257. } else {
  2258. // This is not a fatal error
  2259. DsRolepLogPrint(( DEB_WARN,
  2260. "Failed to establish the session with %ws: 0x%lx\n", SupportDc,
  2261. WinError ));
  2262. }
  2263. //
  2264. // This error is not fatal
  2265. //
  2266. if ( ERROR_SUCCESS != WinError )
  2267. {
  2268. SpmpReportEvent( TRUE,
  2269. EVENTLOG_WARNING_TYPE,
  2270. DSROLERES_FAILED_TO_DELETE_TRUST,
  2271. 0,
  2272. sizeof( ULONG ),
  2273. &WinError,
  2274. 1,
  2275. ParentDomainName );
  2276. DSROLEP_SET_NON_FATAL_ERROR( WinError );
  2277. // Error case is handled
  2278. WinError = ERROR_SUCCESS;
  2279. }
  2280. }
  2281. //
  2282. // Finish our NTFRS demotion
  2283. //
  2284. if ( FrsDemote ) {
  2285. WinError = DsRolepFinishSysVolPropagation( TRUE,
  2286. FALSE );
  2287. if ( ERROR_SUCCESS != WinError ) {
  2288. DsRolepLogOnFailure( WinError,
  2289. DsRolepLogPrint(( DEB_TRACE,
  2290. "Failed to finish system volume demotion (%d)\n",
  2291. WinError )) );
  2292. if (ERROR_SUCCESS == WinError) {
  2293. DsRolepLogPrint(( DEB_TRACE,
  2294. "Finished system volume demotion\n" ));
  2295. }
  2296. }
  2297. //
  2298. // It is not fatal if the FRS fails at this point
  2299. //
  2300. if ( ERROR_SUCCESS != WinError )
  2301. {
  2302. SpmpReportEvent( TRUE,
  2303. EVENTLOG_WARNING_TYPE,
  2304. DSROLERES_FAILED_TO_DEMOTE_FRS,
  2305. 0,
  2306. sizeof( ULONG ),
  2307. &WinError,
  2308. 0,
  2309. NULL );
  2310. DSROLEP_SET_NON_FATAL_ERROR( WinError );
  2311. }
  2312. // Reset status code
  2313. WinError = ERROR_SUCCESS;
  2314. }
  2315. //
  2316. // Call into the SCE so we can be configured to be a server
  2317. //
  2318. WinError = ( *DsrSceDcPromoteSecurityEx )( DemoteArgs->ImpersonateToken,
  2319. SCE_PROMOTE_FLAG_DEMOTE,
  2320. DsRolepStringUpdateCallback );
  2321. if ( ERROR_SUCCESS != WinError ) {
  2322. DsRolepLogOnFailure( WinError,
  2323. DsRolepLogPrint(( DEB_ERROR,
  2324. "Setting security on server files failed with %lu\n",
  2325. WinError )) );
  2326. if (ERROR_SUCCESS == WinError) {
  2327. DsRolepLogPrint(( DEB_TRACE,
  2328. "Set security on server files\n" ));
  2329. }
  2330. // This error has been handled
  2331. WinError = ERROR_SUCCESS;
  2332. }
  2333. //
  2334. // remove all trusted root certificates from DC when the machine will dis-join from the enterprise
  2335. //
  2336. if (DemoteArgs->ServerRole == DsRoleServerStandalone) {
  2337. if (!CertAutoRemove(CERT_AUTO_REMOVE_COMMIT)){
  2338. DsRolepLogPrint(( DEB_WARN,
  2339. "Failed to remove all trusted root certificates from this machine: (%d)\n",
  2340. GetLastError()));
  2341. }
  2342. }
  2343. //Delete persistent shares if not done so already.
  2344. NetStatus = NetShareDel( NULL, L"SYSVOL", 0);
  2345. if(NetStatus != ERROR_SUCCESS && NetStatus != NERR_NetNameNotFound) {
  2346. DsRolepLogPrint(( DEB_WARN,
  2347. "Failed to destroy the share SYSVOL. Failed with %d\n", NetStatus ));
  2348. }
  2349. NetStatus = NetShareDel( NULL, L"NETLOGON", 0);
  2350. if(NetStatus != ERROR_SUCCESS && NetStatus != NERR_NetNameNotFound) {
  2351. DsRolepLogPrint(( DEB_WARN,
  2352. "Failed to destroy the share NETLOGON. Failed with %d\n", NetStatus ));
  2353. }
  2354. //
  2355. // Notify the time server we have completed the demotion
  2356. //
  2357. {
  2358. DWORD dwTimeFlags = W32TIME_DEMOTE;
  2359. if ( DemoteArgs->LastDcInDomain ) {
  2360. //
  2361. // If this is the last Dc in Domain then
  2362. // include this flag.
  2363. //
  2364. dwTimeFlags |= W32TIME_DEMOTE_LAST_DC_IN_DOMAIN;
  2365. }
  2366. (*DsrW32TimeDcPromo)( dwTimeFlags );
  2367. }
  2368. //
  2369. // At this point we have successfully completed the demotion
  2370. //
  2371. ASSERT( ERROR_SUCCESS == WinError );
  2372. //
  2373. // Clear errors components may have erroneously set while running
  2374. //
  2375. DsRolepClearErrors();
  2376. DemoteExit:
  2377. if ( Policy ) {
  2378. LsaClose( Policy );
  2379. }
  2380. if ( Credentials ) {
  2381. RtlFreeHeap( RtlProcessHeap(), 0, Credentials );
  2382. }
  2383. if ( pDnsRRInfo ) {
  2384. ( *DsrNtdsFreeDnsRRInfo )(pDnsRRInfo);
  2385. }
  2386. //
  2387. // Tear down the session to the parent, if we have one
  2388. //
  2389. if ( IPCConnection ) {
  2390. RtlRunDecodeUnicodeString( DemoteArgs->Decode, &DemoteArgs->Password );
  2391. IgnoreError = ImpNetpManageIPCConnect( DemoteArgs->ImpersonateToken,
  2392. SupportDc,
  2393. DemoteArgs->Account,
  2394. DemoteArgs->Password.Buffer,
  2395. (NETSETUPP_DISCONNECT_IPC|NETSETUPP_USE_LOTS_FORCE) );
  2396. RtlRunEncodeUnicodeString( &DemoteArgs->Decode, &DemoteArgs->Password );
  2397. if ( IgnoreError != ERROR_SUCCESS ) {
  2398. DsRolepLogPrint(( DEB_WARN,
  2399. "Failed to destroy the session with %ws: 0x%lx\n", SupportDc,
  2400. IgnoreError ));
  2401. }
  2402. IPCConnection = FALSE;
  2403. }
  2404. //
  2405. // Reset our operation handle
  2406. //
  2407. if ( !fNoNetworkOperations ) {
  2408. DsRolepSetOperationDone( DSROLEP_OP_DEMOTION, WinError );
  2409. } else {
  2410. DsRolepSetOperationDone( DSROLEP_OP_DEMOTION_FORCED, WinError );
  2411. }
  2412. DsRolepFreeArgumentBlock( &ArgumentBlock, FALSE );
  2413. LsaFreeMemory( DnsDomainInfo );
  2414. RtlFreeHeap( RtlProcessHeap(), 0, ParentDomainName );
  2415. NetApiBufferFree( DomainControllerInfo );
  2416. ExitThread( WinError );
  2417. return( WinError );
  2418. DemoteUndo:
  2419. //
  2420. // Assert that aomething went wrong if we are here
  2421. //
  2422. ASSERT( ERROR_SUCCESS != WinError );
  2423. //
  2424. // We shouldn't be here if we are in an unrollable state
  2425. //
  2426. ASSERT( FALSE == Unrollable );
  2427. if ( FrsDemote ) {
  2428. IgnoreError = DsRolepFinishSysVolPropagation( FALSE,
  2429. FALSE );
  2430. DsRolepLogOnFailure( IgnoreError,
  2431. DsRolepLogPrint(( DEB_WARN,
  2432. "Failed to abort system volume demotion (%d)\n",
  2433. IgnoreError )) );
  2434. FrsDemote = FALSE;
  2435. }
  2436. if ( NotifiedNetlogonToDeregister ) {
  2437. //
  2438. // "NlDcDemotionCompleted" sounds strange here since the demotion
  2439. // failed. However, the meaning is that netlogon should now continue
  2440. // to perform as if demotion is not running. No need to set in the
  2441. // success case since NETLOGON won't be restarted.
  2442. //
  2443. Status = I_NetNotifyDsChange( NlDcDemotionCompleted );
  2444. IgnoreError = RtlNtStatusToDosError( Status );
  2445. DsRolepLogOnFailure( IgnoreError,
  2446. DsRolepLogPrint(( DEB_WARN,
  2447. "Failed to tell NETLOGON that demotion is over (%d)\n",
  2448. IgnoreError )) );
  2449. NotifiedNetlogonToDeregister = FALSE;
  2450. }
  2451. if ( RestartNetlogon ) {
  2452. IgnoreError = DsRolepStartNetlogon();
  2453. DsRolepLogOnFailure( IgnoreError,
  2454. DsRolepLogPrint(( DEB_WARN,
  2455. "Failed to restart netlogon (%d)\n",
  2456. IgnoreError )) );
  2457. RestartNetlogon = FALSE;
  2458. }
  2459. if ( DomainControllerServicesChanged ) {
  2460. IgnoreError = DsRolepConfigureDomainControllerServices( DSROLEP_SERVICES_REVERT );
  2461. DsRolepLogOnFailure( IgnoreError,
  2462. DsRolepLogPrint(( DEB_WARN,
  2463. "Failed to rollback domain controller services configuration (%d)\n",
  2464. IgnoreError )) );
  2465. DomainControllerServicesChanged = FALSE;
  2466. }
  2467. if ( DomainServicesChanged ) {
  2468. IgnoreError = DsRolepConfigureDomainServices( DSROLEP_SERVICES_REVERT );
  2469. DsRolepLogOnFailure( IgnoreError,
  2470. DsRolepLogPrint(( DEB_WARN,
  2471. "Failed to rollback domain controller services configuration (%d)\n",
  2472. IgnoreError )) );
  2473. DomainServicesChanged = FALSE;
  2474. }
  2475. if ( DsPrepareDemote ) {
  2476. IgnoreError = ( *DsrNtdsPrepareForDemotionUndo ) ();
  2477. DsRolepLogOnFailure( IgnoreError,
  2478. DsRolepLogPrint(( DEB_WARN,
  2479. "Failed to undo directory service preparation for demotion (%d)\n",
  2480. IgnoreError )) );
  2481. DsPrepareDemote = FALSE;
  2482. }
  2483. //
  2484. // Ok -- we have rolled back, make sure we still have an error and then
  2485. // exit
  2486. //
  2487. ASSERT( ERROR_SUCCESS != WinError );
  2488. goto DemoteExit;
  2489. }