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.

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