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.

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