Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1425 lines
34 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ophandle.c
  5. Abstract:
  6. Routines to manipulate the global operation handle
  7. Author:
  8. Colin Brace (ColinBr) April 5, 1999
  9. Environment:
  10. User Mode
  11. Revision History:
  12. Reorganized from
  13. Mac McLain (MacM) Feb 10, 1997
  14. --*/
  15. #include <setpch.h>
  16. #include <dssetp.h>
  17. #include <lsarpc.h>
  18. #include <samrpc.h>
  19. #include <samisrv.h>
  20. #include <db.h>
  21. #include <confname.h>
  22. #include <loadfn.h>
  23. #include <ntdsa.h>
  24. #include <dsconfig.h>
  25. #include <attids.h>
  26. #include <dsp.h>
  27. #include <lsaisrv.h>
  28. #include <malloc.h>
  29. #include <dsgetdc.h>
  30. #include <lmcons.h>
  31. #include <lmaccess.h>
  32. #include <lmapibuf.h>
  33. #include <lmerr.h>
  34. #include <netsetp.h>
  35. #include <spmgr.h> // For SetupPhase definition
  36. #include "secure.h"
  37. #include "ophandle.h"
  38. //
  39. // Global data -- init'ed to an idle state in DsRoleInitialize
  40. //
  41. DSROLEP_OPERATION_HANDLE DsRolepCurrentOperationHandle;
  42. DWORD
  43. DsRolepInitializeOperationHandle(
  44. VOID
  45. )
  46. /*++
  47. Routine Description:
  48. Does the initialization of the operation handle. The operation handle controls state
  49. and actions of the ds setup apis
  50. Arguments:
  51. VOID
  52. Returns:
  53. ERROR_SUCCESS - Success
  54. --*/
  55. {
  56. DWORD Win32Err = ERROR_SUCCESS;
  57. OBJECT_ATTRIBUTES EventAttr;
  58. UNICODE_STRING EventName;
  59. NTSTATUS Status = STATUS_SUCCESS;
  60. //
  61. // Grab the lock
  62. //
  63. LockOpHandle();
  64. if ( DSROLEP_IDLE != DsRolepCurrentOperationHandle.OperationState ) {
  65. //
  66. // Not idle? Bail
  67. //
  68. Win32Err = ERROR_PROMOTION_ACTIVE;
  69. } else {
  70. Win32Err = DsRolepGetImpersonationToken(&DsRolepCurrentOperationHandle.ClientToken);
  71. if (ERROR_SUCCESS != Win32Err) {
  72. DsRolepCurrentOperationHandle.ClientToken=NULL;
  73. DsRolepLogPrintRoutine(DEB_WARN, "Cannot get user Token for Format Message: %ul\n",
  74. Win32Err);
  75. Win32Err = ERROR_SUCCESS;
  76. //if Error log and continue
  77. }
  78. //
  79. // We are idle, and hence ready to perform a role change
  80. //
  81. RtlInitUnicodeString(&EventName, DSROLEP_EVENT_NAME);
  82. InitializeObjectAttributes(&EventAttr, &EventName, 0, NULL, NULL);
  83. Status = NtCreateEvent( &DsRolepCurrentOperationHandle.CompletionEvent,
  84. EVENT_ALL_ACCESS,
  85. &EventAttr,
  86. NotificationEvent,
  87. FALSE);
  88. if (Status == STATUS_OBJECT_NAME_COLLISION ) {
  89. //
  90. // If the event exists but the operation active flag is clear, we'll
  91. // go ahead and use the event
  92. //
  93. Status = NtResetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  94. }
  95. if ( NT_SUCCESS( Status ) ) {
  96. //
  97. // Create the cancel event
  98. //
  99. Status = NtCreateEvent( &DsRolepCurrentOperationHandle.CancelEvent,
  100. EVENT_MODIFY_STATE | SYNCHRONIZE ,
  101. NULL,
  102. NotificationEvent,
  103. FALSE );
  104. if ( NT_SUCCESS( Status ) ) {
  105. //
  106. // We are ready to roll!
  107. //
  108. DsRolepCurrentOperationHandle.OperationState = DSROLEP_RUNNING;
  109. //
  110. // Set the initial message
  111. //
  112. DsRolepCurrentOperationHandle.MsgIndex = DSROLERES_STARTING;
  113. }
  114. }
  115. if ( NT_SUCCESS( Status ) ) {
  116. //
  117. // Load the functions we'll need
  118. //
  119. Win32Err = DsRolepLoadSetupFunctions();
  120. }
  121. }
  122. //
  123. // Release the lock
  124. //
  125. UnlockOpHandle();
  126. if ( ERROR_SUCCESS != Win32Err
  127. || !NT_SUCCESS( Status ) ) {
  128. if ( ERROR_SUCCESS == Win32Err ) {
  129. Win32Err = RtlNtStatusToDosError( Status );
  130. }
  131. DsRolepLogPrint(( DEB_ERROR, "Internal error trying to initialize operation handle (%lu).\n", Win32Err ));
  132. //
  133. // Reset the handle state
  134. //
  135. DsRolepResetOperationHandle( DSROLEP_IDLE );
  136. }
  137. return( Win32Err );
  138. }
  139. DWORD
  140. DsRolepResetOperationHandle(
  141. DSROLEP_OPERATION_STATE OpState
  142. )
  143. /*++
  144. Routine Description:
  145. Resets the operation handle following a failed or successful completion
  146. of the operation
  147. Arguments:
  148. VOID
  149. Returns:
  150. ERROR_SUCCESS - Success
  151. --*/
  152. {
  153. DWORD Win32Err = ERROR_SUCCESS;
  154. OBJECT_ATTRIBUTES EventAttr;
  155. UNICODE_STRING EventName;
  156. NTSTATUS Status = STATUS_SUCCESS;
  157. // These are the only two states that make sense
  158. ASSERT( (OpState == DSROLEP_IDLE) || (OpState == DSROLEP_NEED_REBOOT) );
  159. //
  160. // Lock the operation handle
  161. //
  162. LockOpHandle();
  163. // It should always be active
  164. ASSERT( DSROLEP_OPERATION_ACTIVE( DsRolepCurrentOperationHandle.OperationState) );
  165. if ( DSROLEP_OPERATION_ACTIVE( DsRolepCurrentOperationHandle.OperationState) )
  166. {
  167. if(DsRolepCurrentOperationHandle.ClientToken){
  168. CloseHandle(DsRolepCurrentOperationHandle.ClientToken);
  169. DsRolepCurrentOperationHandle.ClientToken = NULL;
  170. }
  171. //
  172. // Release the resource of the operation handle
  173. //
  174. if ( DsRolepCurrentOperationHandle.CompletionEvent ) {
  175. Status = NtClose( DsRolepCurrentOperationHandle.CompletionEvent );
  176. DsRolepCurrentOperationHandle.CompletionEvent = NULL;
  177. if ( !NT_SUCCESS( Status ) ) {
  178. DsRoleDebugOut(( DEB_TRACE_DS,
  179. "Failed to close event handle: 0x%lx\n", Status ));
  180. }
  181. }
  182. if ( DsRolepCurrentOperationHandle.CancelEvent ) {
  183. Status = NtClose( DsRolepCurrentOperationHandle.CancelEvent );
  184. DsRolepCurrentOperationHandle.CancelEvent = NULL;
  185. if ( !NT_SUCCESS( Status ) ) {
  186. DsRoleDebugOut(( DEB_TRACE_DS,
  187. "Failed to close event handle: 0x%lx\n", Status ));
  188. }
  189. }
  190. if ( DsRolepCurrentOperationHandle.OperationThread != NULL ) {
  191. CloseHandle( DsRolepCurrentOperationHandle.OperationThread );
  192. DsRolepCurrentOperationHandle.OperationThread = NULL;
  193. }
  194. //
  195. // Unload the global functions
  196. //
  197. DsRolepUnloadSetupFunctions();
  198. //
  199. // Clear the static variables
  200. //
  201. DsRolepResetOperationHandleLockHeld();
  202. //
  203. // Reset the operation state
  204. //
  205. DsRolepCurrentOperationHandle.OperationState = OpState;
  206. }
  207. //
  208. // Release the lock
  209. //
  210. UnlockOpHandle();
  211. if ( !NT_SUCCESS( Status ) ) {
  212. Win32Err = RtlNtStatusToDosError( Status );
  213. }
  214. return( Win32Err );
  215. }
  216. VOID
  217. DsRolepResetOperationHandleLockHeld(
  218. VOID
  219. )
  220. /*++
  221. Routine Description:
  222. Resets the operation handle following a failed or successful completion of the operation
  223. Arguments:
  224. VOID
  225. Returns:
  226. VOID
  227. --*/
  228. {
  229. ASSERT( DsRolepCurrentThreadOwnsLock() );
  230. if ( DsRolepCurrentOperationHandle.Parameter1 ) {
  231. LocalFree( DsRolepCurrentOperationHandle.Parameter1 );
  232. DsRolepCurrentOperationHandle.Parameter1 = NULL;
  233. }
  234. if ( DsRolepCurrentOperationHandle.Parameter2 ) {
  235. LocalFree( DsRolepCurrentOperationHandle.Parameter2 );
  236. DsRolepCurrentOperationHandle.Parameter2 = NULL;
  237. }
  238. if ( DsRolepCurrentOperationHandle.Parameter3 ) {
  239. LocalFree( DsRolepCurrentOperationHandle.Parameter3 );
  240. DsRolepCurrentOperationHandle.Parameter3 = NULL;
  241. }
  242. if ( DsRolepCurrentOperationHandle.Parameter4 ) {
  243. LocalFree( DsRolepCurrentOperationHandle.Parameter4 );
  244. DsRolepCurrentOperationHandle.Parameter4 = NULL;
  245. }
  246. DsRolepCurrentOperationHandle.CompletionEvent = NULL;
  247. DsRolepCurrentOperationHandle.OperationState = DSROLEP_IDLE;
  248. DsRolepCurrentOperationHandle.OperationStatus = 0;
  249. DsRolepCurrentOperationHandle.MsgIndex = 0;
  250. DsRolepCurrentOperationHandle.DisplayStringCount = 0;
  251. DsRolepCurrentOperationHandle.MsgModuleHandle = NULL;
  252. DsRolepCurrentOperationHandle.UpdateStringDisplayable = NULL;
  253. DsRolepCurrentOperationHandle.FinalResultStringDisplayable = NULL;
  254. DsRolepCurrentOperationHandle.InstalledSiteName = NULL;
  255. DsRolepCurrentOperationHandle.OperationResultFlags = 0;
  256. ASSERT( DsRolepCurrentThreadOwnsLock() );
  257. return;
  258. }
  259. DWORD
  260. DsRolepSetCurrentOperationStatus(
  261. IN ULONG MsgIndex,
  262. IN PVOID Parameter1,
  263. IN PVOID Parameter2,
  264. IN PVOID Parameter3,
  265. IN PVOID Parameter4
  266. )
  267. /*++
  268. Routine Description:
  269. Internal routine for updating the current operation handle statics
  270. Arguments:
  271. MsgIndex - Display message resource index
  272. Parameter1 - First display parameter
  273. Parameter2 - Second display parameter
  274. Parameter3 - Third display parameter
  275. Parameter4 - Fourth display parameter
  276. Returns:
  277. ERROR_SUCCESS - Success
  278. --*/
  279. {
  280. DWORD Win32Err = ERROR_SUCCESS;
  281. ULONG Size;
  282. ASSERT( MsgIndex != 0 );
  283. //
  284. // Grab the lock
  285. //
  286. LockOpHandle();
  287. DsRolepCurrentOperationHandle.MsgIndex = MsgIndex;
  288. //
  289. // Release previously held parameters
  290. //
  291. if ( DsRolepCurrentOperationHandle.Parameter1 ) {
  292. LocalFree( DsRolepCurrentOperationHandle.Parameter1 );
  293. DsRolepCurrentOperationHandle.Parameter1 = NULL;
  294. }
  295. if ( DsRolepCurrentOperationHandle.Parameter2 ) {
  296. LocalFree( DsRolepCurrentOperationHandle.Parameter2 );
  297. DsRolepCurrentOperationHandle.Parameter2 = NULL;
  298. }
  299. if ( DsRolepCurrentOperationHandle.Parameter3 ) {
  300. LocalFree( DsRolepCurrentOperationHandle.Parameter3 );
  301. DsRolepCurrentOperationHandle.Parameter3 = NULL;
  302. }
  303. if ( DsRolepCurrentOperationHandle.Parameter4 ) {
  304. LocalFree( DsRolepCurrentOperationHandle.Parameter4 );
  305. DsRolepCurrentOperationHandle.Parameter4 = NULL;
  306. }
  307. //
  308. // Copy the new ones in
  309. //
  310. if ( Parameter1 ) {
  311. Size = (wcslen( Parameter1 ) + 1) * sizeof(WCHAR);
  312. DsRolepCurrentOperationHandle.Parameter1 = LocalAlloc( 0, Size );
  313. if ( !DsRolepCurrentOperationHandle.Parameter1 ) {
  314. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  315. goto ReleaseLock;
  316. }
  317. wcscpy( DsRolepCurrentOperationHandle.Parameter1, Parameter1 );
  318. }
  319. if ( Parameter2 ) {
  320. Size = (wcslen( Parameter2 ) + 1) * sizeof(WCHAR);
  321. DsRolepCurrentOperationHandle.Parameter2 = LocalAlloc( 0, Size );
  322. if ( !DsRolepCurrentOperationHandle.Parameter2 ) {
  323. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  324. goto ReleaseLock;
  325. }
  326. wcscpy( DsRolepCurrentOperationHandle.Parameter2, Parameter2 );
  327. }
  328. if ( Parameter3 ) {
  329. Size = (wcslen( Parameter3 ) + 1) * sizeof(WCHAR);
  330. DsRolepCurrentOperationHandle.Parameter3 = LocalAlloc( 0, Size );
  331. if ( !DsRolepCurrentOperationHandle.Parameter3 ) {
  332. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  333. goto ReleaseLock;
  334. }
  335. wcscpy( DsRolepCurrentOperationHandle.Parameter3, Parameter3 );
  336. }
  337. if ( Parameter4 ) {
  338. Size = (wcslen( Parameter4 ) + 1) * sizeof(WCHAR);
  339. DsRolepCurrentOperationHandle.Parameter4 = LocalAlloc( 0, Size );
  340. if ( !DsRolepCurrentOperationHandle.Parameter4 ) {
  341. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  342. goto ReleaseLock;
  343. }
  344. wcscpy( DsRolepCurrentOperationHandle.Parameter4, Parameter4 );
  345. }
  346. {
  347. PWSTR DisplayString;
  348. DWORD E2;
  349. E2 = DsRolepFormatOperationString(
  350. DsRolepCurrentOperationHandle.MsgIndex,
  351. &DisplayString,
  352. DsRolepCurrentOperationHandle.Parameter1,
  353. DsRolepCurrentOperationHandle.Parameter2,
  354. DsRolepCurrentOperationHandle.Parameter3,
  355. DsRolepCurrentOperationHandle.Parameter4 );
  356. if ( E2 == ERROR_SUCCESS ) {
  357. DsRolepLogPrint(( DEB_TRACE, "%ws", DisplayString ));
  358. MIDL_user_free( DisplayString );
  359. }
  360. }
  361. ReleaseLock:
  362. //
  363. // Don't forget to release the lock
  364. //
  365. UnlockOpHandle();
  366. return( Win32Err );
  367. }
  368. DWORD
  369. DsRolepSetFailureMessage(
  370. IN DWORD FailureStatus,
  371. IN ULONG MsgIndex,
  372. IN PVOID Parameter1,
  373. IN PVOID Parameter2,
  374. IN PVOID Parameter3,
  375. IN PVOID Parameter4
  376. )
  377. /*++
  378. Routine Description:
  379. Internal routine for updating the failure return string
  380. Arguments:
  381. FailureStatus - Error code for the failure
  382. MsgIndex - Display message resource index
  383. Parameter1 - First display parameter
  384. Parameter2 - Second display parameter
  385. Parameter3 - Third display parameter
  386. Parameter4 - Fourth display parameter
  387. Returns:
  388. ERROR_SUCCESS - Success
  389. --*/
  390. {
  391. DWORD Win32Err = ERROR_SUCCESS;
  392. PWSTR DisplayString = NULL;
  393. ASSERT( MsgIndex != 0 );
  394. Win32Err = DsRolepFormatOperationString( MsgIndex,
  395. &DisplayString,
  396. Parameter1,
  397. Parameter2,
  398. Parameter3,
  399. Parameter4 );
  400. if ( Win32Err == ERROR_SUCCESS ) {
  401. Win32Err = DsRolepStringErrorUpdateCallback( DisplayString, FailureStatus );
  402. MIDL_user_free( DisplayString );
  403. }
  404. return( Win32Err );
  405. }
  406. DWORD
  407. DsRolepSetOperationDone(
  408. IN DWORD Flags,
  409. IN DWORD OperationStatus
  410. )
  411. /*++
  412. Routine Description:
  413. Indicates that the requested operation has completed
  414. Arguments:
  415. Flags -- currently : DSROLEP_OP_DEMOTION
  416. DSROLEP_OP_PROMOTION
  417. OperationStatus - Final status of the requsted operation
  418. Returns:
  419. ERROR_SUCCESS - Success
  420. --*/
  421. {
  422. NTSTATUS Status = STATUS_SUCCESS;
  423. //
  424. // Grab the lock
  425. //
  426. LockOpHandle();
  427. DSROLEP_CURRENT_OP0( DSROLEEVT_PROMOTION_COMPLETE );
  428. DsRolepCurrentOperationHandle.OperationState = DSROLEP_FINISHED;
  429. if ( DsRolepCurrentOperationHandle.OperationStatus == 0
  430. || (OperationStatus == ERROR_CANCELLED) ) {
  431. DsRolepCurrentOperationHandle.OperationStatus = OperationStatus;
  432. }
  433. if ( ERROR_SUCCESS == DsRolepCurrentOperationHandle.OperationStatus ) {
  434. //
  435. // Log an event indicating the role has changed
  436. //
  437. DWORD MsgId = 0;
  438. if ( Flags & DSROLEP_OP_DEMOTION ) {
  439. MsgId = DSROLERES_DEMOTE_SUCCESS;
  440. } else if ( Flags & DSROLEP_OP_PROMOTION ) {
  441. MsgId = DSROLERES_PROMOTE_SUCCESS;
  442. } else {
  443. ASSERT( FALSE && !"Bad Parameter" );
  444. }
  445. SpmpReportEvent( TRUE,
  446. EVENTLOG_INFORMATION_TYPE,
  447. MsgId,
  448. 0,
  449. 0,
  450. NULL,
  451. 0 );
  452. }
  453. //
  454. // If the operation was cancelled, give the same error message every
  455. // time
  456. //
  457. if ( ERROR_CANCELLED == DsRolepCurrentOperationHandle.OperationStatus ) {
  458. (VOID) DsRolepSetFailureMessage( ERROR_CANCELLED,
  459. DSROLERES_OP_CANCELLED,
  460. NULL, NULL, NULL, NULL );
  461. }
  462. //
  463. // Signal the completion event
  464. //
  465. Status = NtSetEvent( DsRolepCurrentOperationHandle.CompletionEvent, NULL );
  466. DsRoleDebugOut(( DEB_TRACE_DS, "DsRolepSetOperationDone[ %lu ]\n",
  467. OperationStatus ));
  468. //
  469. // Release the lock
  470. //
  471. UnlockOpHandle();
  472. DsRolepLogPrint(( DEB_TRACE,
  473. "DsRolepSetOperationDone returned %lu\n",
  474. RtlNtStatusToDosError( Status ) ));
  475. return( RtlNtStatusToDosError( Status ) );
  476. }
  477. DWORD
  478. DsRolepGetDcOperationProgress(
  479. IN PDSROLE_SERVEROP_HANDLE DsOperationHandle,
  480. IN OUT PDSROLER_SERVEROP_STATUS *ServerOperationStatus
  481. )
  482. /*++
  483. Routine Description:
  484. Implementation of the RPC server for determining the current level of progress of an
  485. operation
  486. Arguments:
  487. DsOperationHandle - Handle to an open operation
  488. ServerOperationStatus - Where the status is returned.
  489. Returns:
  490. ERROR_SUCCESS - Success
  491. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  492. --*/
  493. {
  494. DWORD Win32Err = ERROR_SUCCESS;
  495. //
  496. // Grab the lock
  497. //
  498. LockOpHandle();
  499. //
  500. // Allocate the return structure
  501. //
  502. *ServerOperationStatus = MIDL_user_allocate( sizeof( DSROLER_SERVEROP_STATUS ) );
  503. if ( *ServerOperationStatus == NULL ) {
  504. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  505. } else {
  506. //
  507. // Build the return string
  508. //
  509. if ( DsRolepCurrentOperationHandle.MsgIndex == 0 ) {
  510. ( *ServerOperationStatus )->CurrentOperationDisplayString = MIDL_user_allocate(
  511. ( wcslen( DsRolepCurrentOperationHandle.UpdateStringDisplayable ) + 1 ) *
  512. sizeof( WCHAR ) );
  513. if ( ( *ServerOperationStatus )->CurrentOperationDisplayString == NULL ) {
  514. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  515. } else {
  516. wcscpy( ( *ServerOperationStatus )->CurrentOperationDisplayString,
  517. DsRolepCurrentOperationHandle.UpdateStringDisplayable );
  518. //
  519. // Set the status flags if they exist
  520. //
  521. if ( DsRolepCurrentOperationHandle.OperationState == DSROLEP_RUNNING_NON_CRITICAL ) {
  522. ( *ServerOperationStatus )->OperationStatus =
  523. DSROLE_CRITICAL_OPERATIONS_COMPLETED;
  524. } else {
  525. ( *ServerOperationStatus )->OperationStatus = 0;
  526. }
  527. ( *ServerOperationStatus )->CurrentOperationDisplayStringIndex =
  528. DsRolepCurrentOperationHandle.DisplayStringCount == 0 ? 0 :
  529. DsRolepCurrentOperationHandle.DisplayStringCount - 1;
  530. }
  531. } else {
  532. Win32Err = DsRolepFormatOperationString(
  533. DsRolepCurrentOperationHandle.MsgIndex,
  534. &( *ServerOperationStatus )->CurrentOperationDisplayString,
  535. DsRolepCurrentOperationHandle.Parameter1,
  536. DsRolepCurrentOperationHandle.Parameter2,
  537. DsRolepCurrentOperationHandle.Parameter3,
  538. DsRolepCurrentOperationHandle.Parameter4 );
  539. }
  540. if ( Win32Err != ERROR_SUCCESS ) {
  541. MIDL_user_free( *ServerOperationStatus );
  542. *ServerOperationStatus = NULL;
  543. }
  544. }
  545. //
  546. // If the operation isn't completed, return that information to the caller
  547. //
  548. if ( Win32Err == ERROR_SUCCESS &&
  549. DsRolepCurrentOperationHandle.OperationState != DSROLEP_FINISHED ) {
  550. Win32Err = ERROR_IO_PENDING;
  551. }
  552. //
  553. // Release the lock
  554. //
  555. UnlockOpHandle();
  556. return( Win32Err );
  557. }
  558. DWORD
  559. DsRolepFormatOperationString(
  560. IN ULONG MsgId,
  561. OUT LPWSTR *FormattedString,
  562. ...
  563. )
  564. /*++
  565. Routine Description:
  566. Allocates and formats the buffer string to be returned
  567. Arguments:
  568. MsgId - Which message id to format
  569. FormattedString - Where the string is allocated. Allocation uses MIDL_user_allocate
  570. ... - va_list of arguments for the formatted string
  571. Returns:
  572. ERROR_SUCCESS - Success
  573. ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
  574. --*/
  575. {
  576. DWORD Win32Err = ERROR_SUCCESS;
  577. WCHAR MsgBuffer[ 512 + 1];
  578. PWSTR Msg = MsgBuffer;
  579. ULONG MsgLength = (sizeof(MsgBuffer) / sizeof(MsgBuffer[0]) ) - 1;
  580. ULONG Length;
  581. BOOL fSuccess = FALSE;
  582. va_list ArgList;
  583. va_start( ArgList, FormattedString );
  584. //
  585. // Load the module handle for lsasrv.dll, so we can get our messages
  586. //
  587. if ( DsRolepCurrentOperationHandle.MsgModuleHandle == NULL ) {
  588. DsRolepCurrentOperationHandle.MsgModuleHandle = GetModuleHandle( L"LSASRV" );
  589. ASSERT( DsRolepCurrentOperationHandle.MsgModuleHandle );
  590. if ( DsRolepCurrentOperationHandle.MsgModuleHandle == NULL ) {
  591. return( GetLastError() );
  592. }
  593. }
  594. //
  595. // Get the required buffer size
  596. //
  597. //
  598. // FormatMessage complains when given a NULL input buffer, so we'll pass in one, even though
  599. // it won't be used because of the size being 0.
  600. //
  601. fSuccess = ImpersonateLoggedOnUser(DsRolepCurrentOperationHandle.ClientToken);
  602. // if we couldn't impersonate we continue anyway.
  603. if (!fSuccess) {
  604. DsRolepLogPrintRoutine(DEB_WARN, "Cannot get user locale for Format Message: %ul\n",
  605. GetLastError());
  606. }
  607. Length = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  608. DsRolepCurrentOperationHandle.MsgModuleHandle,
  609. MsgId, 0, Msg, MsgLength, &ArgList );
  610. if ( Length == 0 ) {
  611. Win32Err = GetLastError();
  612. ASSERT( Win32Err != ERROR_MR_MID_NOT_FOUND );
  613. if ( Win32Err == ERROR_INSUFFICIENT_BUFFER ) {
  614. Length = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  615. DsRolepCurrentOperationHandle.MsgModuleHandle,
  616. MsgId, 0, ( PWSTR )&Msg, 0, &ArgList );
  617. if ( Length == 0 ) {
  618. Win32Err = GetLastError();
  619. } else {
  620. Win32Err = ERROR_SUCCESS;
  621. }
  622. }
  623. }
  624. if (fSuccess) {
  625. fSuccess = RevertToSelf();
  626. if (!fSuccess) {
  627. DsRolepLogPrintRoutine(DEB_WARN, "Cannot reset to system security setting: %ul\n",
  628. GetLastError());
  629. }
  630. }
  631. if( Win32Err == ERROR_SUCCESS ) {
  632. //
  633. // Allocate a buffer
  634. //
  635. Length = ( wcslen( Msg ) + 1 ) * sizeof( WCHAR );
  636. *FormattedString = MIDL_user_allocate( Length );
  637. if ( *FormattedString == NULL ) {
  638. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  639. } else {
  640. RtlCopyMemory( *FormattedString, Msg, Length );
  641. }
  642. }
  643. if ( Msg != MsgBuffer ) {
  644. LocalFree( Msg );
  645. }
  646. return( Win32Err );
  647. }
  648. VOID
  649. DsRolepSetCriticalOperationsDone(
  650. VOID
  651. )
  652. /*++
  653. Routine Description:
  654. Indicates to our current operation status block that the critical portion of the install
  655. has been completed...
  656. Arguments:
  657. VOID
  658. Returns:
  659. VOID
  660. --*/
  661. {
  662. //
  663. // Grab the lock
  664. //
  665. LockOpHandle();
  666. DsRolepCurrentOperationHandle.OperationState = DSROLEP_RUNNING_NON_CRITICAL;
  667. //
  668. // Release the lock
  669. //
  670. UnlockOpHandle();
  671. return;
  672. }
  673. VOID
  674. DsRolepIncrementDisplayStringCount(
  675. VOID
  676. )
  677. /*++
  678. Routine Description:
  679. Increments the count of the successfully started display update strings. This is always
  680. the index into the list of DisplayStrings PLUS ONE.
  681. Arguments:
  682. VOID
  683. Returns:
  684. VOID
  685. --*/
  686. {
  687. //
  688. // Grab the lock
  689. //
  690. LockOpHandle();
  691. DsRolepCurrentOperationHandle.DisplayStringCount++;
  692. //
  693. // Release the lock
  694. //
  695. UnlockOpHandle();
  696. return;
  697. }
  698. DWORD
  699. DsRolepGetDcOperationResults(
  700. IN PDSROLE_SERVEROP_HANDLE DsOperationHandle,
  701. OUT PDSROLER_SERVEROP_RESULTS *ServerOperationResults
  702. )
  703. /*++
  704. Routine Description:
  705. Gets the results of the final operation. If the operation has not yet completed, this
  706. function will block until it does
  707. Arguments:
  708. DsOperationHandle - Handle to an open operation
  709. ServerOperationResults - Where the result is returned.
  710. Returns:
  711. ERROR_SUCCESS - Success
  712. ERROR_INVALID_PARAMETER - A bad results pointer was given
  713. --*/
  714. {
  715. DWORD Win32Err = ERROR_SUCCESS;
  716. NTSTATUS Status = STATUS_SUCCESS;
  717. DSROLEP_OPERATION_STATE OpState;
  718. BOOLEAN fNeedReboot = FALSE;
  719. //
  720. // Parameter checking
  721. //
  722. if ( !ServerOperationResults ) {
  723. return ERROR_INVALID_PARAMETER;
  724. }
  725. //
  726. // Make sure an operation is active
  727. //
  728. LockOpHandle();
  729. OpState = DsRolepCurrentOperationHandle.OperationState;
  730. UnlockOpHandle();
  731. //
  732. // It's an error if the operation isn't active
  733. //
  734. if ( !DSROLEP_OPERATION_ACTIVE( OpState ) ) {
  735. return ERROR_NO_PROMOTION_ACTIVE;
  736. }
  737. //
  738. // Wait for the operation to complete
  739. //
  740. Status = NtWaitForSingleObject( DsRolepCurrentOperationHandle.CompletionEvent, TRUE, NULL );
  741. if ( NT_SUCCESS( Status ) ) {
  742. //
  743. // Lock the handle
  744. //
  745. LockOpHandle();
  746. //
  747. // Allocate the return structure
  748. //
  749. *ServerOperationResults = MIDL_user_allocate( sizeof( DSROLER_SERVEROP_RESULTS ) );
  750. if ( *ServerOperationResults == NULL ) {
  751. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  752. } else {
  753. ( *ServerOperationResults )->OperationResultsFlags = 0;
  754. //
  755. // Build the return string
  756. //
  757. if ( DsRolepCurrentOperationHandle.OperationStatus != ERROR_SUCCESS ||
  758. DsRolepCurrentOperationHandle.MsgIndex == 0 ) {
  759. DSROLEP_MIDL_ALLOC_AND_COPY_STRING_ERROR(
  760. ( *ServerOperationResults )->OperationStatusDisplayString,
  761. DsRolepCurrentOperationHandle.OperationStatus != ERROR_SUCCESS ?
  762. DsRolepCurrentOperationHandle.FinalResultStringDisplayable :
  763. DsRolepCurrentOperationHandle.UpdateStringDisplayable,
  764. Win32Err );
  765. } else {
  766. Win32Err = DsRolepFormatOperationString(
  767. DsRolepCurrentOperationHandle.MsgIndex,
  768. &( *ServerOperationResults )->OperationStatusDisplayString,
  769. DsRolepCurrentOperationHandle.Parameter1,
  770. DsRolepCurrentOperationHandle.Parameter2,
  771. DsRolepCurrentOperationHandle.Parameter3,
  772. DsRolepCurrentOperationHandle.Parameter4 );
  773. }
  774. if ( Win32Err == ERROR_SUCCESS ) {
  775. ( *ServerOperationResults )->OperationStatus =
  776. DsRolepCurrentOperationHandle.OperationStatus;
  777. DsRoleDebugOut(( DEB_TRACE_DS,
  778. "Returning status %lu\n",
  779. DsRolepCurrentOperationHandle.OperationStatus ));
  780. // If the operation finished successfully, we need
  781. // a reboot
  782. if ( ERROR_SUCCESS == DsRolepCurrentOperationHandle.OperationStatus )
  783. {
  784. fNeedReboot = TRUE;
  785. }
  786. }
  787. //
  788. // Return the site name, if it exists
  789. //
  790. if ( Win32Err == ERROR_SUCCESS ) {
  791. DSROLEP_MIDL_ALLOC_AND_COPY_STRING_ERROR(
  792. ( *ServerOperationResults)->ServerInstalledSite,
  793. DsRolepCurrentOperationHandle.InstalledSiteName,
  794. Win32Err );
  795. if ( Win32Err != ERROR_SUCCESS ) {
  796. MIDL_user_free(
  797. ( *ServerOperationResults )->OperationStatusDisplayString );
  798. }
  799. }
  800. //
  801. // Set the flags, if necessary
  802. //
  803. if ( Win32Err == ERROR_SUCCESS ) {
  804. ( *ServerOperationResults )->OperationResultsFlags |=
  805. DsRolepCurrentOperationHandle.OperationResultFlags;
  806. }
  807. if ( Win32Err != ERROR_SUCCESS ) {
  808. MIDL_user_free( *ServerOperationResults );
  809. *ServerOperationResults = NULL;
  810. }
  811. UnlockOpHandle();
  812. //
  813. // Reset our current operation handle
  814. //
  815. DsRolepResetOperationHandle( fNeedReboot ? DSROLEP_NEED_REBOOT : DSROLEP_IDLE );
  816. }
  817. }
  818. if ( Win32Err == ERROR_SUCCESS ) {
  819. Win32Err = RtlNtStatusToDosError( Status );
  820. }
  821. return( Win32Err );
  822. }
  823. DWORD
  824. DsRolepOperationResultFlagsCallBack(
  825. IN DWORD Flags
  826. )
  827. /*++
  828. Routine Description:
  829. Internal routine for updating the Operation Results Flags
  830. Arguments:
  831. Flags - DWORD of flags to | with current flags
  832. Returns:
  833. ERROR_SUCCESS - Success
  834. --*/
  835. {
  836. DWORD Win32Err = ERROR_SUCCESS;
  837. LockOpHandle();
  838. DsRolepCurrentOperationHandle.OperationResultFlags |= Flags;
  839. UnlockOpHandle();
  840. return( Win32Err );
  841. }
  842. DWORD
  843. DsRolepStringUpdateCallback(
  844. IN PWSTR StringUpdate
  845. )
  846. /*++
  847. Routine Description:
  848. Internal routine for updating the current operation handle statics
  849. Arguments:
  850. StringUpdate - Displayables string to set in place of the current parameters
  851. Returns:
  852. ERROR_SUCCESS - Success
  853. --*/
  854. {
  855. DWORD Win32Err = ERROR_SUCCESS;
  856. ULONG len;
  857. //
  858. // Grab the lock
  859. //
  860. LockOpHandle();
  861. DsRolepCurrentOperationHandle.MsgIndex = 0;
  862. DsRolepCurrentOperationHandle.Parameter1 = 0;
  863. DsRolepCurrentOperationHandle.Parameter2 = 0;
  864. DsRolepCurrentOperationHandle.Parameter3 = 0;
  865. DsRolepCurrentOperationHandle.Parameter4 = 0;
  866. if ( StringUpdate ) {
  867. DsRolepLogPrint(( DEB_TRACE, "%ws\n", StringUpdate ));
  868. }
  869. DsRoleDebugOut(( DEB_TRACE_UPDATE,
  870. "DsRolepSetCurrentOperationStatus for string %ws\n",
  871. StringUpdate ));
  872. if ( DsRolepCurrentOperationHandle.UpdateStringDisplayable ) {
  873. RtlFreeHeap( RtlProcessHeap(), 0, DsRolepCurrentOperationHandle.UpdateStringDisplayable );
  874. }
  875. DsRolepCurrentOperationHandle.UpdateStringDisplayable =
  876. RtlAllocateHeap( RtlProcessHeap(), 0,
  877. ( wcslen( StringUpdate ) + 1 ) * sizeof( WCHAR ) );
  878. if ( DsRolepCurrentOperationHandle.UpdateStringDisplayable == NULL ) {
  879. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  880. } else {
  881. wcscpy( DsRolepCurrentOperationHandle.UpdateStringDisplayable, StringUpdate );
  882. }
  883. //
  884. // Don't forget to release the lock
  885. //
  886. UnlockOpHandle();
  887. return( Win32Err );
  888. }
  889. DWORD
  890. DsRolepStringErrorUpdateCallback(
  891. IN PWSTR String,
  892. IN DWORD ErrorCode
  893. )
  894. /*++
  895. Routine Description:
  896. Internal routine for updating the last failure operation
  897. Arguments:
  898. String - Displayable error string
  899. ErrorCode - Error code associated with this failure
  900. Returns:
  901. ERROR_SUCCESS - Success
  902. --*/
  903. {
  904. DWORD Win32Err = ERROR_SUCCESS;
  905. //
  906. // Grab the lock
  907. //
  908. LockOpHandle();
  909. if ( (ERROR_SUCCESS == DsRolepCurrentOperationHandle.OperationStatus)
  910. || (ERROR_CANCELLED == ErrorCode) ) {
  911. //
  912. // Cancel overides previous error codes
  913. //
  914. if ( DsRolepCurrentOperationHandle.FinalResultStringDisplayable ) {
  915. RtlFreeHeap( RtlProcessHeap(), 0, DsRolepCurrentOperationHandle.FinalResultStringDisplayable );
  916. }
  917. DsRolepCurrentOperationHandle.FinalResultStringDisplayable =
  918. RtlAllocateHeap( RtlProcessHeap(), 0, ( wcslen( String ) + 1 ) * sizeof( WCHAR ) );
  919. if ( DsRolepCurrentOperationHandle.FinalResultStringDisplayable == NULL ) {
  920. Win32Err = ERROR_NOT_ENOUGH_MEMORY;
  921. } else {
  922. wcscpy( DsRolepCurrentOperationHandle.FinalResultStringDisplayable, String );
  923. DsRolepCurrentOperationHandle.OperationStatus = ErrorCode;
  924. DsRoleDebugOut(( DEB_TRACE_UPDATE,
  925. "DsRolepStringErrorUpdateCallback for error %lu and string %ws\n",
  926. ErrorCode,
  927. String ));
  928. DsRolepLogPrint(( DEB_TRACE, "Error - %ws (%d)\n", String, ErrorCode ));
  929. }
  930. }
  931. //
  932. // Release the lock
  933. //
  934. UnlockOpHandle();
  935. return( Win32Err );
  936. }
  937. DWORD
  938. DsRolepSetOperationHandleSiteName(
  939. IN LPWSTR SiteName
  940. )
  941. {
  942. LockOpHandle();
  943. DsRolepCurrentOperationHandle.InstalledSiteName = SiteName;
  944. UnlockOpHandle();
  945. return ERROR_SUCCESS;
  946. }
  947. BOOLEAN
  948. DsRolepCurrentThreadOwnsLock(
  949. VOID
  950. )
  951. /*++
  952. Routine Description
  953. Tests wether the current thread owns the lock
  954. --*/
  955. {
  956. ULONG_PTR ExclusiveOwnerThread = (ULONG_PTR) DsRolepCurrentOperationHandle.CurrentOpLock.ExclusiveOwnerThread;
  957. ULONG_PTR CurrentThread = (ULONG_PTR) (NtCurrentTeb())->ClientId.UniqueThread;
  958. if ((DsRolepCurrentOperationHandle.CurrentOpLock.NumberOfActive <0) && (ExclusiveOwnerThread==CurrentThread))
  959. return TRUE;
  960. return FALSE;
  961. }
  962. VOID
  963. DsRolepClearErrors(
  964. VOID
  965. )
  966. /*++
  967. Routine Description
  968. This routine clears the global status. The purpose of this is to
  969. clear errors that components may have set after the demotion is
  970. unrollable and should not return errors.
  971. --*/
  972. {
  973. //
  974. // Grab the lock
  975. //
  976. LockOpHandle();
  977. if ( DsRolepCurrentOperationHandle.OperationStatus != ERROR_SUCCESS ) {
  978. //
  979. // Set a warning that something went wrong
  980. //
  981. DsRolepLogPrint(( DEB_TRACE, "Clearing a global error" ));
  982. DSROLEP_SET_NON_FATAL_ERROR( DsRolepCurrentOperationHandle.OperationStatus );
  983. }
  984. if ( DsRolepCurrentOperationHandle.FinalResultStringDisplayable ) {
  985. RtlFreeHeap( RtlProcessHeap(), 0, DsRolepCurrentOperationHandle.FinalResultStringDisplayable );
  986. DsRolepCurrentOperationHandle.FinalResultStringDisplayable = NULL;
  987. }
  988. DsRolepCurrentOperationHandle.OperationStatus = ERROR_SUCCESS;
  989. //
  990. // Release the lock
  991. //
  992. UnlockOpHandle();
  993. }