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.

1229 lines
32 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1998
  3. All rights reserved
  4. File: CALLBACK.CPP
  5. ***************************************************************************/
  6. #include "pch.h"
  7. #include "utils.h"
  8. #include "tasks.h"
  9. #include "setup.h"
  10. #include "callback.h"
  11. #include "logging.h"
  12. #include "userenv.h"
  13. // Must have this...
  14. extern "C" {
  15. #include <sysprep_.h>
  16. //
  17. // SYSPREP globals
  18. //
  19. extern BOOL NoSidGen;
  20. extern BOOL PnP;
  21. }
  22. DEFINE_MODULE("RIPREP")
  23. DWORD g_WorkerThreadId = 0;
  24. HANDLE g_WorkerThreadHandle = INVALID_HANDLE_VALUE;
  25. HWND g_hMainWindow = NULL;
  26. HWND g_hTasksDialog = NULL;
  27. DWORD g_NeedDlg = NULL;
  28. #define NCOLORSHADES 32
  29. //
  30. // Spin( )
  31. //
  32. DWORD
  33. Spin( )
  34. {
  35. TraceFunc( "Spin( )\n" );
  36. DWORD dwResult;
  37. MSG Msg;
  38. // We will spin in here until the end
  39. while ( WAIT_TIMEOUT == (dwResult = WaitForSingleObject( g_WorkerThreadHandle, 50 )) )
  40. {
  41. while ( PeekMessage( &Msg, NULL, NULL, NULL, PM_REMOVE ) )
  42. {
  43. if (Msg.message == WM_SYSKEYUP)
  44. continue; // ignore
  45. if (Msg.message == WM_KEYDOWN)
  46. continue; // ignore
  47. if (Msg.message == WM_KEYUP)
  48. continue; // ignore
  49. TranslateMessage( &Msg );
  50. DispatchMessage( &Msg );
  51. }
  52. }
  53. RETURN(dwResult);
  54. }
  55. //
  56. // WorkerThreadProc( )
  57. //
  58. DWORD
  59. WorkerThreadProc(
  60. LPVOID lParam )
  61. {
  62. // Place in the log all the gathered information for the wizard
  63. // as well as system APIs.
  64. LogMsg( L"Server : %s\r\n", g_ServerName );
  65. LogMsg( L"Image Dir : %s\r\n", g_MirrorDir );
  66. LogMsg( L"Language : %s\r\n", g_Language );
  67. LogMsg( L"Architecture: %s\r\n", g_Architecture );
  68. LogMsg( L"Description : %s\r\n", g_Description );
  69. LogMsg( L"HelpText : %s\r\n", g_HelpText );
  70. LogMsg( L"SystemRoot : %s\r\n", g_SystemRoot );
  71. LogMsg( L"Winnt Dir : %s\r\n", g_WinntDirectory );
  72. // Start the IMIRROR task list
  73. DWORD dw = ProcessToDoItems( );
  74. DebugMsg( "ProcessToDoItems( ) completed: 0x%08x\n", dw );
  75. return dw;
  76. }
  77. HWND g_hParent = NULL;
  78. //
  79. // MainWindowProc ( )
  80. //
  81. LRESULT CALLBACK
  82. MainWindowProc(
  83. HWND hDlg,
  84. UINT uMsg,
  85. WPARAM wParam,
  86. LPARAM lParam )
  87. {
  88. static WCHAR szTitle[ 256 ];
  89. static DWORD dwTitleLength;
  90. static HFONT BigBoldFont = NULL;
  91. switch(uMsg)
  92. {
  93. case WM_NCCREATE:
  94. return TRUE; // keep going
  95. case WM_CREATE:
  96. {
  97. DWORD dw;
  98. dw = LoadString( g_hinstance, IDS_APPNAME, szTitle, ARRAYSIZE(szTitle));
  99. Assert(dw);
  100. dwTitleLength = wcslen( szTitle );
  101. }
  102. break;
  103. case WM_PAINT:
  104. {
  105. PAINTSTRUCT ps;
  106. RECT rc;
  107. LOGBRUSH brush;
  108. HBRUSH hBrush;
  109. HBRUSH hOldBrush;
  110. HFONT hFont;
  111. INT n = 0;
  112. BeginPaint( hDlg, &ps );
  113. rc.left = 0;
  114. rc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
  115. rc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
  116. INT yDelta= max(rc.bottom/NCOLORSHADES,1); // height of one shade band
  117. rc.top = rc.bottom - yDelta;
  118. // Shade the background
  119. while (rc.top >= 0)
  120. {
  121. brush.lbColor = RGB(0, 0, (256*n)/NCOLORSHADES);
  122. brush.lbStyle = BS_SOLID;
  123. hBrush = (HBRUSH) CreateBrushIndirect( &brush );
  124. hOldBrush = (HBRUSH) SelectObject(ps.hdc, hBrush);
  125. FillRect( ps.hdc, &rc, hBrush );
  126. SelectObject(ps.hdc, hOldBrush);
  127. DeleteObject(hBrush);
  128. rc.top -= yDelta;
  129. rc.bottom -= yDelta;
  130. n++;
  131. }
  132. if ( !BigBoldFont )
  133. {
  134. HFONT Font;
  135. LOGFONT LogFont;
  136. WCHAR FontSizeString[24];
  137. INT FontSize;
  138. Font = (HFONT) GetStockObject( SYSTEM_FONT );
  139. if ( (Font ) && GetObject( Font, sizeof(LOGFONT), &LogFont) )
  140. {
  141. DWORD dw = LoadString( g_hinstance,
  142. IDS_LARGEFONTNAME,
  143. LogFont.lfFaceName,
  144. LF_FACESIZE);
  145. Assert( dw );
  146. LogFont.lfWeight = 700;
  147. FontSize = yDelta;
  148. LogFont.lfHeight = 0 - (GetDeviceCaps(ps.hdc,LOGPIXELSY) * FontSize / 72);
  149. LogFont.lfWidth = 0;
  150. BigBoldFont = CreateFontIndirect(&LogFont);
  151. }
  152. }
  153. // Redraw the title
  154. SetBkMode( ps.hdc, TRANSPARENT );
  155. SelectObject( ps.hdc, BigBoldFont );
  156. SetTextColor( ps.hdc, RGB( 255, 255, 255 ) );
  157. TextOut(ps.hdc, yDelta, yDelta, szTitle, dwTitleLength );
  158. EndPaint( hDlg, &ps );
  159. }
  160. break;
  161. case WM_CHAR:
  162. case WM_KEYDOWN:
  163. case WM_KEYUP:
  164. case WM_MOUSEACTIVATE:
  165. case WM_MOUSEMOVE:
  166. case WM_MOUSEWHEEL:
  167. break; // ignore
  168. case WM_DESTROY:
  169. if ( BigBoldFont )
  170. DeleteObject( BigBoldFont );
  171. break;
  172. case WM_ERASEBKGND:
  173. // Don't waste time erasing
  174. return TRUE; // non-zero
  175. default:
  176. return DefWindowProc( hDlg, uMsg, wParam, lParam );
  177. }
  178. return FALSE;
  179. }
  180. //
  181. // BeginProcess( )
  182. //
  183. HRESULT
  184. BeginProcess(
  185. HWND hParent)
  186. {
  187. TraceFunc( "BeginProcess( )\n" );
  188. MSG Msg;
  189. WNDCLASSEX wndClass;
  190. ATOM atom;
  191. RECT rc;
  192. HWND hwndDesktop = GetDesktopWindow( );
  193. DWORD dwExStyle;
  194. GetWindowRect( hwndDesktop, &rc );
  195. // Create our window class
  196. ZeroMemory( &wndClass, sizeof(wndClass) );
  197. wndClass.cbSize = sizeof(wndClass);
  198. wndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
  199. wndClass.hInstance = g_hinstance;
  200. wndClass.lpfnWndProc = (WNDPROC) &MainWindowProc;
  201. wndClass.lpszClassName = L"MondoWindow";
  202. wndClass.style = CS_CLASSDC | CS_NOCLOSE;
  203. atom = RegisterClassEx( &wndClass );
  204. Assert( atom );
  205. g_hParent = hParent;
  206. #ifdef DEBUG
  207. dwExStyle = ( g_dwTraceFlags ? 0 : WS_EX_TOPMOST );
  208. #else
  209. dwExStyle = WS_EX_TOPMOST;
  210. #endif
  211. g_hMainWindow = CreateWindowEx( dwExStyle,
  212. L"MondoWindow",
  213. L"",
  214. WS_POPUP | WS_VISIBLE,
  215. GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
  216. GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN),
  217. NULL,
  218. NULL,
  219. g_hinstance,
  220. NULL );
  221. Assert( g_hMainWindow );
  222. g_hTasksDialog = CreateDialog(g_hinstance, MAKEINTRESOURCE(IDD_TASKS), g_hMainWindow, TasksDlgProc );
  223. if ( g_hTasksDialog )
  224. {
  225. g_WorkerThreadHandle = CreateThread( NULL, NULL, WorkerThreadProc, NULL, 0, &g_WorkerThreadId );
  226. Spin( );
  227. SendMessage( g_hTasksDialog, WM_DESTROY, 0, 0 );
  228. }
  229. HRETURN(S_OK);
  230. }
  231. //
  232. // IsFileInExclusionList()
  233. //
  234. BOOLEAN
  235. IsFileInExclusionList(
  236. IN PCWSTR FileName
  237. )
  238. /*++
  239. Description:
  240. This routine searches the exclusion list in our INF file.
  241. Parameters:
  242. FileName : File to search the INF for.
  243. Return Value:
  244. TRUE - The file does exist in the INF
  245. FALSE - The file does not exist in the INF
  246. ++*/
  247. {
  248. #define SKIPFLAG_DIRECTORY 1
  249. #define SKIPFLAG_FILTEREXTENSION 2
  250. PWSTR FullPath = NULL;
  251. PWSTR DirectoryName = NULL;
  252. INFCONTEXT Context;
  253. INT Flags = 0;
  254. WCHAR FilterExtension[10];
  255. BOOLEAN ReturnValue = FALSE;
  256. //
  257. // Make sure we have our INF.
  258. //
  259. if( g_hCompatibilityInf == INVALID_HANDLE_VALUE ) {
  260. //
  261. // Probably hasn't been initialized yet. Assume the
  262. // file isn't in the INF.
  263. //
  264. return FALSE;
  265. }
  266. if( FileName == NULL ) {
  267. return FALSE;
  268. }
  269. //
  270. // Get a local copy of the filename so we can operate on it
  271. // without worry of corrupting the caller's data.
  272. //
  273. if( wcsncmp(FileName, L"\\\\?\\", 4) == 0 ) {
  274. FullPath = (PWSTR)TraceStrDup( FileName+4 );
  275. } else {
  276. FullPath = (PWSTR)TraceStrDup( FileName );
  277. }
  278. if( FullPath == NULL ) {
  279. DebugMsg( "IsFileInExclusionList: Odd pathname %s.\n",
  280. FileName );
  281. return FALSE;
  282. }
  283. //
  284. // See if it's explicitly listed in the INF
  285. //
  286. if (SetupFindFirstLine( g_hCompatibilityInf,
  287. L"FilesToSkipCopy",
  288. FullPath,
  289. &Context)) {
  290. DebugMsg( "IsFileInExclusionList: Found file %s in the INF exclusion list.\n",
  291. FullPath );
  292. ReturnValue = TRUE;
  293. goto Cleanup;
  294. }
  295. //
  296. // The file isn't specifically listed in the INF. See if
  297. // the directory this file is in is listed.
  298. //
  299. // Start whacking file/directory names off the end of the
  300. // path to see if the result is in our exclusion list.
  301. //
  302. //
  303. // Remember the filename.
  304. //
  305. FileName = wcsrchr(FullPath, L'\\');
  306. if( FileName == NULL ) {
  307. DebugMsg( "IsFileInExclusionList: File isn't in exclusion list and has no directory path.\n" );
  308. ReturnValue = FALSE;
  309. goto Cleanup;
  310. }
  311. FileName++;
  312. while( DirectoryName = wcsrchr(FullPath, L'\\') ) {
  313. *DirectoryName = NULL;
  314. if( SetupFindFirstLine( g_hCompatibilityInf,
  315. L"FilesToSkipCopy",
  316. FullPath,
  317. &Context)) {
  318. //
  319. // The directory name *IS* in there. See if we need to
  320. // skip all files in this directory, or only some.
  321. //
  322. Flags = 0;
  323. if( SetupGetIntField( &Context, 1, &Flags) &&
  324. ((Flags & SKIPFLAG_FILTEREXTENSION) == 0)) {
  325. //
  326. // We don't have the filter flag, so we will just
  327. // skip all files in this directory.
  328. //
  329. DebugMsg( "IsFileInExclusionList: Found file %s in %s in the exclusion list (based on the name of his directory).\n",
  330. FileName,
  331. FullPath );
  332. ReturnValue = TRUE;
  333. goto Cleanup;
  334. }
  335. //
  336. // See if we should skip files with a specified extension.
  337. //
  338. if( SetupGetStringField( &Context,
  339. 2,
  340. FilterExtension,
  341. ARRAYSIZE(FilterExtension),
  342. NULL )) {
  343. PCWSTR q = wcsrchr( FileName, L'.' );
  344. if (q) {
  345. q++;
  346. if (_wcsicmp(q, FilterExtension) == 0) {
  347. DebugMsg( "IsFileInExclusionList: Found file %s in %s with extension %s in the exclusion list (based on the directory and extension of the file).\n",
  348. FileName,
  349. FullPath,
  350. q );
  351. ReturnValue = TRUE;
  352. goto Cleanup;
  353. }
  354. }
  355. }
  356. }
  357. }
  358. Cleanup:
  359. if( FullPath ) {
  360. DebugMemoryDelete( FullPath );
  361. }
  362. return ReturnValue;
  363. }
  364. //
  365. // ConvTestErrorFn()
  366. //
  367. NTSTATUS
  368. ConvTestErrorFn(
  369. IN PVOID Context,
  370. IN NTSTATUS Status,
  371. IN IMIRROR_TODO IMirrorFunctionId
  372. )
  373. {
  374. TraceFunc( "ConvTestErrorFn( ... )\n" );
  375. WCHAR szMessage[ 256 ];
  376. DWORD dw;
  377. LBITEMDATA item;
  378. if ( Status != ERROR_SUCCESS )
  379. {
  380. DebugMsg("ERROR REPORTED! : Context 0x%x, Status 0x%x, In Func 0x%x\n", Context, Status, IMirrorFunctionId );
  381. // Error will be logged in TASKS.CPP
  382. item.fSeen = FALSE;
  383. item.pszText = (IMirrorFunctionId == CheckPartitions) ? NULL : (LPWSTR)Context;
  384. item.uState = Status; // used as input and output
  385. item.todo = IMirrorFunctionId;
  386. BOOL b = (BOOL)SendMessage( g_hTasksDialog, WM_ERROR, 0, (LPARAM) &item );
  387. if ( !b )
  388. {
  389. Status = ERROR_REQUEST_ABORTED;
  390. }
  391. else
  392. {
  393. Status = item.uState;
  394. }
  395. if ( Status == ERROR_SUCCESS )
  396. {
  397. dw = LoadString( g_hinstance, IDS_ERROR_IGNORED, szMessage, ARRAYSIZE( szMessage ));
  398. Assert( dw );
  399. }
  400. else if ( Status == STATUS_RETRY )
  401. {
  402. dw = LoadString( g_hinstance, IDS_STATUS_RETRY, szMessage, ARRAYSIZE( szMessage ));
  403. Assert( dw );
  404. }
  405. else // other should be abort
  406. {
  407. Assert( Status == ERROR_REQUEST_ABORTED );
  408. dw = LoadString( g_hinstance, IDS_OPERATION_ABORTED, szMessage, ARRAYSIZE( szMessage ));
  409. Assert( dw );
  410. ClearAllToDoItems(FALSE);
  411. }
  412. Assert( dw );
  413. LogMsg( szMessage );
  414. }
  415. RETURN(Status);
  416. }
  417. NTSTATUS
  418. ConvTestNowDoingFn(
  419. IN PVOID Context,
  420. IN IMIRROR_TODO Function,
  421. IN PWSTR String
  422. )
  423. {
  424. TraceFunc( "ConvTestNowDoingFn( )\n" );
  425. LPWSTR pszMessage;
  426. WCHAR szMessage[ 256 ];
  427. LPWSTR pszString;
  428. HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
  429. INT uCount;
  430. DWORD dw;
  431. LPLBITEMDATA pitem = NULL;
  432. NTSTATUS Status = ERROR_SUCCESS;
  433. static lastToDo = IMirrorNone;
  434. static BOOL fAlreadyAdjusted = FALSE;
  435. if ( String ) {
  436. pszString = (LPWSTR)TraceStrDup( String );
  437. // DebugMsg( "Received: %s\n", String );
  438. } else {
  439. pszString = NULL;
  440. }
  441. // if we are onto another task, mark the previous one done
  442. // and mark this one as started.
  443. if ( lastToDo != Function )
  444. {
  445. uCount = ListBox_GetCount( hwnd );
  446. while (uCount>=0)
  447. {
  448. LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
  449. uCount--;
  450. if ( lResult == LB_ERR )
  451. continue;
  452. pitem = (LPLBITEMDATA) lResult;
  453. pitem->fSeen = TRUE;
  454. if ( pitem->todo == Function )
  455. {
  456. if ( pitem->uState == STATE_NOTSTARTED )
  457. {
  458. pitem->uState = STATE_STARTED;
  459. InvalidateRect( hwnd, NULL, TRUE ); // force redraw
  460. }
  461. }
  462. else
  463. {
  464. if ( pitem->uState == STATE_STARTED )
  465. {
  466. pitem->uState = STATE_DONE;
  467. InvalidateRect( hwnd, NULL, TRUE ); // force redraw
  468. }
  469. }
  470. }
  471. lastToDo = Function;
  472. }
  473. switch (Function) {
  474. case IMirrorInitialize:
  475. dw = LoadString( g_hinstance, IDS_INITIALIZING, szMessage, ARRAYSIZE(szMessage) );
  476. Assert(dw);
  477. break;
  478. case VerifySystemIsNt5:
  479. dw = LoadString( g_hinstance, IDS_VERIFYING_WINDOWS_VERSION, szMessage, ARRAYSIZE(szMessage) );
  480. Assert(dw);
  481. break;
  482. case CheckPartitions:
  483. dw = LoadString( g_hinstance, IDS_ANALYZING_PARTITIONS, szMessage, ARRAYSIZE(szMessage) );
  484. Assert(dw);
  485. break;
  486. case CopyPartitions:
  487. dw = LoadString( g_hinstance, IDS_COPYING_PARTITIONS, szMessage, ARRAYSIZE(szMessage) );
  488. Assert(dw);
  489. break;
  490. case CopyFiles:
  491. if ( pszString == NULL )
  492. { // Only need to do this once.
  493. WCHAR ProfilesDirectory[MAX_PATH];
  494. OSVERSIONINFO OsVersion;
  495. //
  496. // Begin SYSPREP ops
  497. //
  498. if( !NoSidGen && !IsSetupClPresent() )
  499. {
  500. LBITEMDATA item;
  501. // Error will be logged in TASKS.CPP
  502. item.fSeen = FALSE;
  503. item.pszText = L"SETUPCL.EXE";
  504. item.uState = ERROR_FILE_NOT_FOUND;
  505. item.todo = Function;
  506. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  507. Status = STATUS_REQUEST_ABORTED;
  508. }
  509. //
  510. // Prepare to run Setupcl. This will also call into
  511. // RunExternalUniqueness which gives others a chance to save
  512. // any info that needs to be copied to the server.
  513. //
  514. if (!NoSidGen && !PrepForSidGen())
  515. {
  516. LBITEMDATA item;
  517. // Error will be logged in TASKS.CPP
  518. item.fSeen = FALSE;
  519. item.pszText = L"Preparing SIDs error";
  520. item.uState = ERROR_FILE_NOT_FOUND;
  521. item.todo = Function;
  522. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  523. Status = STATUS_REQUEST_ABORTED;
  524. }
  525. //
  526. // Syprep cleanup which updates files that are required to be copied
  527. // over to the server.
  528. //
  529. if (!AdjustFiles())
  530. {
  531. LBITEMDATA item;
  532. // Error will be logged in TASKS.CPP
  533. item.fSeen = FALSE;
  534. item.pszText = L"Adjusting files error";
  535. item.uState = ERROR_FILE_NOT_FOUND;
  536. item.todo = Function;
  537. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  538. Status = STATUS_REQUEST_ABORTED;
  539. }
  540. #ifndef _IA64_
  541. //
  542. // Make sure we're on something reasonably current before
  543. // we attempt to ReArm the license. The APIs just didn't
  544. // exist on win2k.
  545. //
  546. OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  547. if( (GetVersionEx(&OsVersion)) &&
  548. (OsVersion.dwMajorVersion >= 5) &&
  549. (OsVersion.dwMinorVersion >= 1) ) {
  550. dw = ReArm();
  551. if( dw != ERROR_SUCCESS ) {
  552. LBITEMDATA item;
  553. // Error will be logged in TASKS.CPP
  554. item.fSeen = FALSE;
  555. item.pszText = L"Rearming";
  556. item.uState = dw;
  557. item.todo = Function;
  558. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  559. Status = STATUS_REQUEST_ABORTED;
  560. }
  561. }
  562. #endif
  563. //
  564. // We need to assign a DirectoryID to the directory containing
  565. // the user profiles. There is no hardcoded DirID for this, so
  566. // we'll make one up and tell Setupapi about it.
  567. //
  568. dw = MAX_PATH;
  569. if( !GetProfilesDirectory( ProfilesDirectory,
  570. &dw ) ) {
  571. //
  572. // We should never get here, but just in case.
  573. //
  574. wcscpy( ProfilesDirectory, L"C:\\Documents and Settings" );
  575. }
  576. if (g_hCompatibilityInf != INVALID_HANDLE_VALUE) {
  577. if( !SetupSetDirectoryId( g_hCompatibilityInf,
  578. PROFILES_DIRID,
  579. ProfilesDirectory ) ) {
  580. ASSERT( FALSE && L"Unable to SetupSetDirectoryId for user profiles" );
  581. }
  582. }
  583. //
  584. // End SYSPREP ops
  585. //
  586. }
  587. else // if ( pszString )
  588. {
  589. if( IsFileInExclusionList(pszString) ) {
  590. //
  591. // It's in the exclusion list.
  592. //
  593. DebugMsg( "ConvTestNowDoingFn: Skipping file %s because it's in the INF exclusion list.\n",
  594. pszString );
  595. RETURN(E_FAIL);
  596. }
  597. }
  598. dw = LoadString( g_hinstance, IDS_COPYING_FILES, szMessage, ARRAYSIZE(szMessage) );
  599. Assert(dw);
  600. break;
  601. case CopyRegistry:
  602. //
  603. // Begin SYSPREP ops
  604. //
  605. Status = ERROR_SUCCESS;
  606. if ( IsDomainMember( ) )
  607. {
  608. RetryUnjoin:
  609. Status = NetUnjoinDomain( NULL, NULL, NULL, 0 );
  610. if ( Status != NERR_Success )
  611. {
  612. LBITEMDATA item;
  613. // Error will be logged in TASKS.CPP
  614. item.fSeen = FALSE;
  615. item.pszText = L"Remove from Domain Error";
  616. item.uState = Status;
  617. item.todo = Function;
  618. SendMessage( g_hTasksDialog, WM_ERROR, 0, (LPARAM) &item );
  619. if ( Status == ERROR_SUCCESS )
  620. {
  621. dw = LoadString( g_hinstance, IDS_ERROR_IGNORED, szMessage, ARRAYSIZE( szMessage ));
  622. }
  623. else if ( Status == STATUS_RETRY )
  624. {
  625. dw = LoadString( g_hinstance, IDS_STATUS_RETRY, szMessage, ARRAYSIZE( szMessage ));
  626. }
  627. else // other should be abort
  628. {
  629. Assert( Status == ERROR_REQUEST_ABORTED );
  630. dw = LoadString( g_hinstance, IDS_OPERATION_ABORTED, szMessage, ARRAYSIZE( szMessage ));
  631. }
  632. Assert( dw );
  633. LogMsg( szMessage );
  634. if ( Status == STATUS_RETRY )
  635. {
  636. goto RetryUnjoin;
  637. }
  638. }
  639. }
  640. if( !fAlreadyAdjusted )
  641. {
  642. WCHAR szSrcPath[MAX_PATH];
  643. fAlreadyAdjusted = TRUE;
  644. wsprintf( szSrcPath, L"%s\\ristndrd.sif", g_ImageName );
  645. //
  646. // We are going to munge some system values. Prevent us for bailing
  647. // without a reboot.
  648. //
  649. g_fRebootOnExit = TRUE;
  650. if ( Status != ERROR_SUCCESS
  651. || !RemoveNetworkSettings(szSrcPath)
  652. || !AdjustRegistry( FALSE /* no, do not remove networking*/) )
  653. {
  654. LBITEMDATA item;
  655. // Error will be logged in TASKS.CPP
  656. item.fSeen = FALSE;
  657. item.pszText = L"Registry Error";
  658. item.uState = GetLastError( );
  659. item.todo = Function;
  660. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  661. Status = STATUS_REQUEST_ABORTED;
  662. }
  663. }
  664. if ( Status == ERROR_SUCCESS )
  665. {
  666. NukeMruList();
  667. }
  668. else
  669. {
  670. ClearAllToDoItems(FALSE);
  671. }
  672. //
  673. // End SYSPREP ops
  674. //
  675. dw = LoadString( g_hinstance, IDS_COPYING_REGISTRY, szMessage, ARRAYSIZE( szMessage ));
  676. Assert(dw);
  677. break;
  678. case PatchDSEntries:
  679. dw = LoadString( g_hinstance, IDS_UPDATING_DS_ENTRIES, szMessage, ARRAYSIZE( szMessage ));
  680. Assert(dw);
  681. break;
  682. case RebootSystem:
  683. dw = LoadString( g_hinstance, IDS_REBOOTING_SYSTEM, szMessage, ARRAYSIZE( szMessage ));
  684. Assert(dw);
  685. break;
  686. default:
  687. dw = LoadString( g_hinstance, IDS_DOING_UNKNOWN_TASK, szMessage, ARRAYSIZE( szMessage ));
  688. Assert(dw);
  689. }
  690. pszMessage = (LPWSTR) TraceStrDup( szMessage );
  691. if ( !pszMessage )
  692. RETURN(E_OUTOFMEMORY);
  693. PostMessage( g_hTasksDialog, WM_UPDATE, (WPARAM)pszMessage, (LPARAM)pszString );
  694. // These were handed off to another thread. Don't track them anymore in
  695. // this thread.
  696. DebugMemoryDelete( pszMessage );
  697. if (pszString) {
  698. DebugMemoryDelete( pszString );
  699. }
  700. if ( Status != NO_ERROR )
  701. {
  702. if( pitem ) {
  703. pitem->uState = STATE_ERROR;
  704. }
  705. InvalidateRect( hwnd, NULL, TRUE ); // force redraw
  706. ClearAllToDoItems(FALSE);
  707. }
  708. RETURN(Status);
  709. }
  710. NTSTATUS
  711. ConvTestGetServerFn(
  712. IN PVOID Context,
  713. OUT PWSTR Server,
  714. IN OUT PULONG Length
  715. )
  716. {
  717. TraceFunc( "ConvTestGetServerFn( )\n" );
  718. StrCpy( Server, g_ServerName );
  719. *Length = (wcslen(Server) + 1) * sizeof(WCHAR);
  720. DebugMsg( "Sending: %s\n", Server );
  721. RETURN((*Length == sizeof(WCHAR)) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS);
  722. }
  723. NTSTATUS
  724. ConvTestGetMirrorDirFn(
  725. IN PVOID Context,
  726. OUT PWSTR Mirror,
  727. IN OUT PULONG Length
  728. )
  729. {
  730. TraceFunc( "ConvTestGetMirrorDirFn( )\n" );
  731. wsprintf( Mirror,
  732. L"\\\\%s\\REMINST\\Setup\\%s\\%s\\%s",
  733. g_ServerName,
  734. g_Language,
  735. REMOTE_INSTALL_IMAGE_DIR_W,
  736. g_MirrorDir );
  737. CreateDirectory( Mirror, NULL );
  738. wsprintf( Mirror,
  739. L"\\\\%s\\REMINST\\Setup\\%s\\%s\\%s\\%s",
  740. g_ServerName,
  741. g_Language,
  742. REMOTE_INSTALL_IMAGE_DIR_W,
  743. g_MirrorDir,
  744. g_Architecture );
  745. CreateDirectory( Mirror, NULL );
  746. *Length = (wcslen(Mirror) + 1) * sizeof(WCHAR);
  747. DebugMsg( "Sending: %s\n", Mirror );
  748. RETURN((*Length == sizeof(WCHAR)) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS);
  749. }
  750. NTSTATUS
  751. ConvTestFileCreateFn(
  752. IN PVOID Context,
  753. IN PWSTR FileName,
  754. IN ULONG FileAction,
  755. IN ULONG Status
  756. )
  757. {
  758. TraceFunc( "ConvTestFileCreateFn( )\n" );
  759. if (Status != 0) {
  760. if( IsFileInExclusionList( FileName ) ) {
  761. //
  762. // It's in the exclusion list.
  763. //
  764. DebugMsg( "ConvTestFileCreateFn: Skipping file %s because it's in the INF exclusion list.\n",
  765. FileName );
  766. Status = 0;
  767. }
  768. if (Status != 0) {
  769. Status = ConvTestErrorFn( FileName, Status, CopyFiles );
  770. }
  771. } else {
  772. DebugMsg("created %ws\n", FileName);
  773. }
  774. RETURN(Status);
  775. }
  776. NTSTATUS
  777. ConvTestReinitFn(
  778. IN PVOID Context
  779. )
  780. {
  781. TraceFunc( "ConvTestReinitFn()\n" );
  782. WCHAR Tmp[256] = L"c";
  783. if (Tmp[0] != 'c') {
  784. ClearAllToDoItems(FALSE);
  785. InitToDo();
  786. }
  787. RETURN(STATUS_SUCCESS);
  788. }
  789. NTSTATUS
  790. ConvTestGetSetupFn(
  791. IN PVOID Context,
  792. IN PWSTR Server,
  793. OUT PWSTR SetupPath,
  794. IN OUT PULONG Length
  795. )
  796. {
  797. TraceFunc( "ConvTestGetSetupFn()\n" );
  798. wcscpy( SetupPath, g_ImageName );
  799. *Length = wcslen( SetupPath );
  800. DebugMsg( "Sending: %s\n", SetupPath );
  801. RETURN(STATUS_SUCCESS);
  802. }
  803. NTSTATUS
  804. ConvTestSetSystemFn(
  805. IN PVOID Context,
  806. IN PWSTR SystemPath,
  807. IN ULONG Length
  808. )
  809. {
  810. NTSTATUS err;
  811. TraceFunc( "ConvTestSetSystemFn()\n" );
  812. if (Length <= ARRAYSIZE(g_SystemRoot)) {
  813. wcscpy( g_SystemRoot, SystemPath );
  814. err = STATUS_SUCCESS;
  815. } else {
  816. err = ERROR_BAD_LENGTH;
  817. }
  818. RETURN(err);
  819. }
  820. NTSTATUS
  821. ConvAddToDoItemFn(
  822. IN PVOID Context,
  823. IN IMIRROR_TODO Function,
  824. IN PWSTR String,
  825. IN ULONG Length
  826. )
  827. {
  828. LPLBITEMDATA pitem;
  829. HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
  830. WCHAR szMessage[ 256 ];
  831. DWORD dw;
  832. INT uCount;
  833. TraceFunc( "ConvAddToDoItemFn()\n" );
  834. pitem = (LPLBITEMDATA) TraceAlloc( LMEM_FIXED, sizeof(LBITEMDATA));
  835. if ( !pitem)
  836. RETURN(E_OUTOFMEMORY);
  837. switch (Function) {
  838. case IMirrorInitialize:
  839. dw = LoadString( g_hinstance, IDS_INITIALIZE, szMessage, ARRAYSIZE( szMessage ));
  840. Assert(dw);
  841. break;
  842. case VerifySystemIsNt5:
  843. dw = LoadString( g_hinstance, IDS_VERIFY_WINDOWS_VERSION, szMessage, ARRAYSIZE( szMessage ));
  844. Assert(dw);
  845. break;
  846. case CheckPartitions:
  847. dw = LoadString( g_hinstance, IDS_ANALYZE_PARTITIONS, szMessage, ARRAYSIZE( szMessage ));
  848. Assert(dw);
  849. break;
  850. case CopyPartitions:
  851. dw = LoadString( g_hinstance, IDS_COPY_PARTITIONS, szMessage, ARRAYSIZE( szMessage ));
  852. Assert(dw);
  853. break;
  854. case CopyFiles:
  855. dw = LoadString( g_hinstance, IDS_COPY_FILES, szMessage, ARRAYSIZE( szMessage ));
  856. Assert(dw);
  857. break;
  858. case CopyRegistry:
  859. dw = LoadString( g_hinstance, IDS_COPY_REGISTRY, szMessage, ARRAYSIZE( szMessage ));
  860. Assert(dw);
  861. break;
  862. case PatchDSEntries:
  863. dw = LoadString( g_hinstance, IDS_PATH_DS_ENTRIES, szMessage, ARRAYSIZE( szMessage ));
  864. Assert(dw);
  865. break;
  866. case RebootSystem:
  867. dw = LoadString( g_hinstance, IDS_REBOOT_SYSTEM, szMessage, ARRAYSIZE( szMessage ));
  868. Assert(dw);
  869. break;
  870. default:
  871. dw = LoadString( g_hinstance, IDS_UNKNOWN_TASK, szMessage, ARRAYSIZE( szMessage ));
  872. Assert(dw);
  873. }
  874. pitem->pszText = (LPWSTR) TraceStrDup( szMessage );
  875. pitem->uState = STATE_NOTSTARTED;
  876. pitem->todo = Function;
  877. pitem->fSeen = FALSE;
  878. if ( !pitem->pszText )
  879. {
  880. TraceFree( pitem );
  881. RETURN(E_OUTOFMEMORY);
  882. }
  883. // skip the "done" items
  884. uCount = 0;
  885. while (uCount>=0)
  886. {
  887. LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
  888. if ( lResult == LB_ERR )
  889. break;
  890. LPLBITEMDATA panitem = (LPLBITEMDATA) lResult;
  891. if ( panitem->uState == STATE_STARTED )
  892. {
  893. uCount++;
  894. break;
  895. }
  896. if ( panitem->uState != STATE_DONE )
  897. break;
  898. uCount++;
  899. }
  900. // go to end of the "unseen" items
  901. while (uCount>=0)
  902. {
  903. LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
  904. if ( lResult == LB_ERR )
  905. break;
  906. LPLBITEMDATA panitem = (LPLBITEMDATA) lResult;
  907. uCount++;
  908. if ( panitem->fSeen )
  909. {
  910. uCount--;
  911. break;
  912. }
  913. }
  914. ListBox_InsertString( hwnd, uCount, pitem );
  915. InvalidateRect( hwnd, NULL, TRUE ); // force redraw
  916. DebugMsg( "Added ToDo Item (%d): %s\n", uCount, pitem->pszText );
  917. RETURN(STATUS_SUCCESS);
  918. }
  919. NTSTATUS
  920. ConvRemoveToDoItemFn(
  921. IN PVOID Context,
  922. IN IMIRROR_TODO Function,
  923. IN PWSTR String,
  924. IN ULONG Length
  925. )
  926. {
  927. LPLBITEMDATA pitem;
  928. HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
  929. INT uCount;
  930. TraceFunc( "ConvRemoveToDoItemFn()\n" );
  931. uCount = ListBox_GetCount( hwnd );
  932. while (uCount>=0)
  933. {
  934. LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
  935. uCount--;
  936. if ( lResult == LB_ERR )
  937. continue;
  938. pitem = (LPLBITEMDATA) lResult;
  939. if ( pitem->todo == Function )
  940. {
  941. pitem->uState = STATE_STARTED;
  942. break;
  943. }
  944. }
  945. RETURN(STATUS_SUCCESS);
  946. }
  947. NTSTATUS
  948. ConvRebootFn(
  949. IN PVOID Context
  950. )
  951. {
  952. DWORD Error;
  953. // do the last minute things
  954. EndProcess( g_hTasksDialog );
  955. #ifdef DEBUG
  956. // if Debugging, don't reboot
  957. if ( !g_dwTraceFlags )
  958. {
  959. #endif
  960. if (!DoShutdown(FALSE)) {
  961. LBITEMDATA item;
  962. // Error will be logged in TASKS.CPP
  963. item.fSeen = FALSE;
  964. item.pszText = L"Shutdown Error";
  965. item.uState = GetLastError( );
  966. item.todo = RebootSystem;
  967. SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
  968. return item.uState;
  969. }
  970. //
  971. // Prevent the error log from being displayed twice. Since
  972. // we are set to reboot/shutdown now, this flag can be
  973. // safely reset.
  974. //
  975. g_fRebootOnExit = FALSE;
  976. #ifdef DEBUG
  977. }
  978. #endif
  979. return STATUS_SUCCESS;
  980. }
  981. BOOL
  982. DoShutdown(
  983. IN BOOL Restart
  984. )
  985. {
  986. NTSTATUS Status;
  987. BOOLEAN WasEnabled;
  988. Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  989. (BOOLEAN)TRUE,
  990. TRUE,
  991. &WasEnabled
  992. );
  993. if (Status == STATUS_NO_TOKEN) {
  994. //
  995. // No thread token, use the process token
  996. //
  997. Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  998. (BOOLEAN)TRUE,
  999. FALSE,
  1000. &WasEnabled
  1001. );
  1002. }
  1003. if (Restart) {
  1004. return ExitWindowsEx( EWX_REBOOT | EWX_FORCEIFHUNG, 0 );
  1005. } else {
  1006. return InitiateSystemShutdown(NULL, NULL, 0, TRUE, FALSE);
  1007. }
  1008. }