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.

1320 lines
35 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. ***************************************************************************/
  5. #include "pch.h"
  6. DEFINE_MODULE("Utils");
  7. #define SMALL_BUFFER_SIZE 1024
  8. BOOL
  9. x86DetermineSystemPartition(
  10. IN HWND ParentWindow,
  11. OUT PTCHAR SysPartDrive
  12. );
  13. BOOLEAN
  14. GetBuildNumberFromImagePath(
  15. PDWORD pdwVersion,
  16. PCWSTR SearchDir,
  17. PCWSTR SubDir OPTIONAL
  18. );
  19. //
  20. // Centers a dialog.
  21. //
  22. void
  23. CenterDialog(
  24. HWND hwndDlg )
  25. {
  26. RECT rc;
  27. RECT rcScreen;
  28. int x, y;
  29. int cxDlg, cyDlg;
  30. int cxScreen;
  31. int cyScreen;
  32. SystemParametersInfo( SPI_GETWORKAREA, 0, &rcScreen, 0 );
  33. cxScreen = rcScreen.right - rcScreen.left;
  34. cyScreen = rcScreen.bottom - rcScreen.top;
  35. GetWindowRect( hwndDlg, &rc );
  36. cxDlg = rc.right - rc.left;
  37. cyDlg = rc.bottom - rc.top;
  38. y = rcScreen.top + ( ( cyScreen - cyDlg ) / 2 );
  39. x = rcScreen.left + ( ( cxScreen - cxDlg ) / 2 );
  40. SetWindowPos( hwndDlg, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE );
  41. }
  42. //
  43. // Eats all mouse and keyboard messages.
  44. //
  45. void
  46. ClearMessageQueue( void )
  47. {
  48. MSG msg;
  49. while ( PeekMessage( (LPMSG)&msg, NULL, WM_KEYFIRST, WM_MOUSELAST,
  50. PM_NOYIELD | PM_REMOVE ) );
  51. }
  52. //
  53. // Create a message box from resource strings.
  54. //
  55. int
  56. MessageBoxFromStrings(
  57. HWND hParent,
  58. UINT idsCaption,
  59. UINT idsText,
  60. UINT uType )
  61. {
  62. TCHAR szText[ SMALL_BUFFER_SIZE ];
  63. TCHAR szCaption[ SMALL_BUFFER_SIZE ];
  64. DWORD dw;
  65. dw = LoadString( g_hinstance, idsCaption, szCaption, ARRAYSIZE( szCaption ));
  66. Assert( dw );
  67. dw = LoadString( g_hinstance, idsText, szText, ARRAYSIZE( szText ));
  68. Assert( dw );
  69. return MessageBox( hParent, szText, szCaption, uType );
  70. }
  71. //
  72. // Creates a error message box
  73. //
  74. void
  75. MessageBoxFromError(
  76. HWND hParent,
  77. LPTSTR pszTitle,
  78. DWORD dwErr )
  79. {
  80. WCHAR szText[ SMALL_BUFFER_SIZE ];
  81. LPTSTR lpMsgBuf;
  82. if ( dwErr == ERROR_SUCCESS ) {
  83. AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
  84. return;
  85. }
  86. if ( !pszTitle ) {
  87. DWORD dw;
  88. szText[0] = L'\0';
  89. dw = LoadString( g_hinstance, IDS_ERROR, szText, ARRAYSIZE( szText ));
  90. Assert( dw );
  91. pszTitle = szText;
  92. }
  93. if (!FormatMessage(
  94. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  95. NULL,
  96. dwErr,
  97. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  98. (LPTSTR) &lpMsgBuf,
  99. 0,
  100. NULL )) {
  101. lpMsgBuf = NULL;
  102. }
  103. if (lpMsgBuf == NULL) {
  104. AssertMsg( dwErr, "Getting error message failed. Why?" );
  105. return;
  106. }
  107. MessageBox( hParent, lpMsgBuf, pszTitle, MB_OK | MB_ICONERROR );
  108. LocalFree( lpMsgBuf );
  109. }
  110. //
  111. // Creates a error message box
  112. //
  113. void
  114. ErrorBox(
  115. HWND hParent,
  116. LPTSTR pszTitle )
  117. {
  118. DWORD dw;
  119. DWORD dwErr = GetLastError( );
  120. WCHAR szText[ SMALL_BUFFER_SIZE ];
  121. LPTSTR lpMsgBuf;
  122. if ( dwErr == ERROR_SUCCESS ) {
  123. AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
  124. return;
  125. }
  126. if ( !pszTitle ) {
  127. DWORD dw;
  128. dw = LoadString( g_hinstance, IDS_ERROR, szText, ARRAYSIZE( szText ));
  129. Assert( dw );
  130. pszTitle = szText;
  131. }
  132. dw = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  133. NULL,
  134. dwErr,
  135. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  136. (LPTSTR) &lpMsgBuf,
  137. 0,
  138. NULL );
  139. if ( dw != 0 )
  140. {
  141. MessageBox( hParent, lpMsgBuf, pszTitle, MB_OK | MB_ICONERROR );
  142. LocalFree( lpMsgBuf );
  143. }
  144. else
  145. {
  146. WCHAR szString[ 256 ];
  147. dw = LoadString( g_hinstance, IDS_UNDEFINED_ERROR_STRING, szString, ARRAYSIZE(szString));
  148. Assert( dw );
  149. wsprintf( szText, szString, dwErr );
  150. MessageBox( hParent, szText, pszTitle, MB_OK | MB_ICONERROR );
  151. }
  152. }
  153. VOID
  154. SetDialogFont(
  155. IN HWND hdlg,
  156. IN UINT ControlId,
  157. IN MyDlgFont WhichFont
  158. )
  159. {
  160. static HFONT BigBoldFont = NULL;
  161. static HFONT BoldFont = NULL;
  162. static HFONT NormalFont = NULL;
  163. HFONT Font;
  164. LOGFONT LogFont;
  165. WCHAR FontSizeString[24];
  166. int FontSize;
  167. HDC hdc;
  168. switch(WhichFont) {
  169. case DlgFontTitle:
  170. if(!BigBoldFont) {
  171. if ( Font =
  172. (HFONT) SendDlgItemMessage( hdlg, ControlId, WM_GETFONT, 0, 0) )
  173. {
  174. if ( GetObject( Font, sizeof(LOGFONT), &LogFont) )
  175. {
  176. DWORD dw = LoadString( g_hinstance,
  177. IDS_LARGEFONTNAME,
  178. LogFont.lfFaceName,
  179. LF_FACESIZE);
  180. Assert( dw );
  181. dw = LoadString( g_hinstance,
  182. IDS_LARGEFONTSIZE,
  183. FontSizeString,
  184. ARRAYSIZE(FontSizeString));
  185. Assert( dw );
  186. FontSize = wcstoul( FontSizeString, NULL, 10 );
  187. // make sure we at least have some basic font
  188. if (*LogFont.lfFaceName == 0 || FontSize == 0) {
  189. lstrcpy(LogFont.lfFaceName,TEXT("MS Shell Dlg") );
  190. FontSize = 18;
  191. }
  192. LogFont.lfWeight = FW_BOLD;
  193. if ( hdc = GetDC(hdlg) )
  194. {
  195. LogFont.lfHeight =
  196. 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
  197. BigBoldFont = CreateFontIndirect(&LogFont);
  198. ReleaseDC(hdlg,hdc);
  199. }
  200. }
  201. }
  202. }
  203. Font = BigBoldFont;
  204. break;
  205. case DlgFontBold:
  206. if ( !BoldFont )
  207. {
  208. if ( Font =
  209. (HFONT) SendDlgItemMessage( hdlg, ControlId, WM_GETFONT, 0, 0 ))
  210. {
  211. if ( GetObject( Font, sizeof(LOGFONT), &LogFont ) )
  212. {
  213. LogFont.lfWeight = FW_BOLD;
  214. if ( hdc = GetDC( hdlg ) )
  215. {
  216. BoldFont = CreateFontIndirect( &LogFont );
  217. ReleaseDC( hdlg, hdc );
  218. }
  219. }
  220. }
  221. }
  222. Font = BoldFont;
  223. break;
  224. default:
  225. //
  226. // Nothing to do here.
  227. //
  228. Font = NULL;
  229. break;
  230. }
  231. if( Font )
  232. {
  233. SendDlgItemMessage( hdlg, ControlId, WM_SETFONT, (WPARAM) Font, 0 );
  234. }
  235. }
  236. //
  237. // Adjusts and draws a bitmap transparently in the RECT prc.
  238. //
  239. void
  240. DrawBitmap(
  241. HANDLE hBitmap,
  242. LPDRAWITEMSTRUCT lpdis,
  243. LPRECT prc )
  244. {
  245. TraceFunc( "DrawBitmap( ... )\n" );
  246. BITMAP bm;
  247. HDC hDCBitmap;
  248. int dy;
  249. GetObject( hBitmap, sizeof(bm), &bm );
  250. hDCBitmap = CreateCompatibleDC( NULL );
  251. if (hDCBitmap == NULL) {
  252. return;
  253. }
  254. SelectObject( hDCBitmap, hBitmap );
  255. // center the image
  256. dy = 2 + prc->bottom - bm.bmHeight;
  257. StretchBlt( lpdis->hDC, prc->left, prc->top + dy, prc->right, prc->bottom,
  258. hDCBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCAND );
  259. DeleteDC( hDCBitmap );
  260. TraceFuncExit( );
  261. }
  262. //
  263. // Verifies that the user wanted to cancel setup.
  264. //
  265. BOOL
  266. VerifyCancel( HWND hParent )
  267. {
  268. TraceFunc( "VerifyCancel( ... )\n" );
  269. INT iReturn;
  270. BOOL fAbort = FALSE;
  271. iReturn = MessageBoxFromStrings( hParent,
  272. IDS_CANCELCAPTION,
  273. IDS_CANCELTEXT,
  274. MB_YESNO | MB_ICONQUESTION );
  275. if ( iReturn == IDYES ) {
  276. fAbort = TRUE;
  277. }
  278. SetWindowLongPtr( hParent, DWLP_MSGRESULT, ( fAbort ? 0 : -1 ));
  279. g_Options.fAbort = fAbort;
  280. RETURN(!fAbort);
  281. }
  282. //
  283. // RetrieveWorkstationLanguageFromHive
  284. //
  285. HRESULT
  286. RetrieveWorkstationLanguageFromHive(
  287. HWND hDlg )
  288. {
  289. TraceFunc( "RetrieveWorkstationLanguageFromHive( )\n" );
  290. HRESULT hr = S_FALSE;
  291. HINF hinf;
  292. WCHAR szFilepath[ MAX_PATH ];
  293. INFCONTEXT context;
  294. WCHAR szCodePage[ 32 ];
  295. ULONG uResult;
  296. BOOL b;
  297. UINT uLineNum;
  298. LPWSTR psz;
  299. //
  300. // build the path to hivesys.inf
  301. //
  302. wcscpy( szFilepath, g_Options.szSourcePath );
  303. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  304. ConcatenatePaths( szFilepath, L"hivesys.inf" );
  305. //
  306. // open the file
  307. //
  308. hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  309. if ( hinf == INVALID_HANDLE_VALUE ) {
  310. DWORD dwErr = GetLastError( );
  311. switch ( dwErr )
  312. {
  313. case ERROR_FILE_NOT_FOUND:
  314. MessageBoxFromStrings( hDlg, IDS_FILE_NOT_FOUND_TITLE, IDS_FILE_NOT_FOUND_TEXT, MB_OK );
  315. break;
  316. default:
  317. ErrorBox( hDlg, szFilepath );
  318. break;
  319. }
  320. hr = HRESULT_FROM_WIN32( dwErr );
  321. goto Cleanup;
  322. }
  323. // Find the "AddReg" section
  324. b = SetupFindFirstLine( hinf, L"Strings", L"Install_Language", &context );
  325. if ( !b )
  326. {
  327. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  328. ErrorBox( hDlg, szFilepath );
  329. goto Cleanup;
  330. }
  331. b = SetupGetStringField( &context, 1, szCodePage, ARRAYSIZE(szCodePage), NULL );
  332. if ( !b )
  333. {
  334. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  335. ErrorBox( hDlg, szFilepath );
  336. goto Cleanup;
  337. }
  338. g_Options.dwWksCodePage = (WORD) wcstoul( szCodePage, &psz, 16 );
  339. DebugMsg( "Image CodePage = 0x%04x\n", g_Options.dwWksCodePage );
  340. uResult = GetLocaleInfo( PRIMARYLANGID(g_Options.dwWksCodePage),
  341. LOCALE_SENGLANGUAGE,
  342. g_Options.szLanguage,
  343. ARRAYSIZE(g_Options.szLanguage));
  344. if ( uResult == 0 ) {
  345. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  346. ErrorBox( hDlg, szFilepath );
  347. goto Cleanup;
  348. }
  349. DebugMsg( "Image Language: %s\n", g_Options.szLanguage );
  350. // Success!
  351. g_Options.fLanguageSet = TRUE;
  352. hr = S_OK;
  353. Cleanup:
  354. if ( hinf != INVALID_HANDLE_VALUE ) {
  355. SetupCloseInfFile( hinf );
  356. }
  357. HRETURN(hr);
  358. }
  359. //
  360. // CheckImageSource( )
  361. //
  362. HRESULT
  363. CheckImageSource(
  364. HWND hDlg )
  365. {
  366. TraceFunc( "CheckImageSource( ... )\n" );
  367. HRESULT hr = S_FALSE;
  368. WCHAR szFilepath[ MAX_PATH ];
  369. WCHAR szTemp[ 32 ];
  370. BYTE szPidExtraData[ 14 ];
  371. WORD CodePage;
  372. HINF hinf;
  373. UINT uResult;
  374. UINT uLineNum;
  375. DWORD dw;
  376. BOOL b;
  377. LPWSTR psz;
  378. INFCONTEXT context;
  379. //
  380. // build the path to hivesys.inf
  381. //
  382. wcscpy( szFilepath, g_Options.szSourcePath );
  383. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  384. ConcatenatePaths( szFilepath, L"txtsetup.sif" );
  385. //
  386. // open the file
  387. //
  388. hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  389. if ( hinf == INVALID_HANDLE_VALUE ) {
  390. DWORD dwErr = GetLastError( );
  391. switch ( dwErr )
  392. {
  393. case ERROR_FILE_NOT_FOUND:
  394. MessageBoxFromStrings( hDlg, IDS_FILE_NOT_FOUND_TITLE, IDS_FILE_NOT_FOUND_TEXT, MB_OK );
  395. break;
  396. default:
  397. ErrorBox( hDlg, szFilepath );
  398. break;
  399. }
  400. hr = HRESULT_FROM_WIN32( dwErr );
  401. goto Cleanup;
  402. }
  403. #if 0
  404. //
  405. // Allow server installs - adamba 2/21/00
  406. //
  407. b = SetupFindFirstLine( hinf, L"SetupData", L"ProductType", &context );
  408. if ( !b )
  409. {
  410. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  411. if ( hr == ERROR_LINE_NOT_FOUND ) {
  412. MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
  413. } else {
  414. ErrorBox( hDlg, szFilepath );
  415. }
  416. goto Cleanup;
  417. }
  418. b = SetupGetStringField( &context, 1, szTemp, ARRAYSIZE(szTemp), NULL );
  419. if ( !b )
  420. {
  421. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  422. ErrorBox( hDlg, szFilepath );
  423. goto Cleanup;
  424. }
  425. if ( StrCmp( szTemp, L"0" ) )
  426. {
  427. MessageBoxFromStrings( hDlg, IDS_NOT_WORKSTATION_TITLE, IDS_NOT_WORKSTATION_TEXT, MB_OK );
  428. hr = E_FAIL;
  429. goto Cleanup;
  430. }
  431. #endif
  432. b = SetupFindFirstLine( hinf, L"SetupData", L"Architecture", &context );
  433. if ( !b )
  434. {
  435. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  436. if ( hr == ERROR_LINE_NOT_FOUND ) {
  437. MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
  438. } else {
  439. ErrorBox( hDlg, szFilepath );
  440. }
  441. goto Cleanup;
  442. }
  443. b = SetupGetStringField( &context, 1, szTemp, ARRAYSIZE(szTemp), NULL );
  444. if ( !b )
  445. {
  446. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  447. ErrorBox( hDlg, szFilepath );
  448. goto Cleanup;
  449. }
  450. if ( (StrCmp(szTemp,L"i386")) && (StrCmp(szTemp,L"ia64")) )
  451. {
  452. MessageBoxFromStrings( hDlg, IDS_NOT_SUPPORTED_ARCHITECTURE_TITLE, IDS_NOT_SUPPORTED_ARCHITECTURE_TEXT, MB_OK );
  453. hr = E_FAIL;
  454. goto Cleanup;
  455. }
  456. if (StrCmp(g_Options.ProcessorArchitectureString,szTemp))
  457. {
  458. MessageBoxFromStrings( hDlg, IDS_NOT_SUPPORTED_ARCHITECTURE_TITLE, IDS_NOT_SUPPORTED_ARCHITECTURE_TEXT, MB_OK );
  459. hr = E_FAIL;
  460. goto Cleanup;
  461. }
  462. if (!g_Options.fLanguageOverRide) {
  463. hr = RetrieveWorkstationLanguageFromHive( hDlg );
  464. if ( FAILED( hr ) )
  465. goto Cleanup;
  466. }
  467. if (!GetBuildNumberFromImagePath(
  468. &g_Options.dwBuildNumber,
  469. g_Options.szSourcePath,
  470. g_Options.ProcessorArchitectureString)) {
  471. #if 0
  472. MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
  473. hr = E_FAIL;
  474. goto Cleanup;
  475. #else
  476. #endif
  477. }
  478. // Get image Major version
  479. b = SetupFindFirstLine( hinf, L"SetupData", L"MajorVersion", &context );
  480. if ( !b )
  481. {
  482. DWORD dwErr = GetLastError( );
  483. switch ( dwErr )
  484. {
  485. case ERROR_LINE_NOT_FOUND:
  486. MessageBoxFromStrings( hDlg, IDS_LINE_MISSING_CAPTION, IDS_LINE_MISSING_TEXT, MB_OK );
  487. break;
  488. default:
  489. ErrorBox( hDlg, szFilepath );
  490. break;
  491. }
  492. hr = HRESULT_FROM_WIN32( dwErr );
  493. goto Cleanup;
  494. }
  495. b = SetupGetStringField( &context, 1, g_Options.szMajorVersion, ARRAYSIZE(g_Options.szMajorVersion), NULL );
  496. if ( !b )
  497. {
  498. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  499. ErrorBox( hDlg, szFilepath );
  500. goto Cleanup;
  501. }
  502. // Get image Minor version
  503. b = SetupFindFirstLine( hinf, L"SetupData", L"MinorVersion", &context );
  504. if ( !b )
  505. {
  506. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  507. ErrorBox( hDlg, szFilepath );
  508. goto Cleanup;
  509. }
  510. b = SetupGetStringField( &context, 1, g_Options.szMinorVersion, ARRAYSIZE(g_Options.szMinorVersion), NULL );
  511. if ( !b )
  512. {
  513. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  514. ErrorBox( hDlg, szFilepath );
  515. goto Cleanup;
  516. }
  517. // Get image description
  518. if ( !g_Options.fRetrievedWorkstationString )
  519. {
  520. b = SetupFindFirstLine( hinf, L"SetupData", L"LoadIdentifier", &context );
  521. if ( !b )
  522. {
  523. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  524. ErrorBox( hDlg, szFilepath );
  525. goto Cleanup;
  526. }
  527. b = SetupGetStringField(
  528. &context,
  529. 1,
  530. g_Options.szDescription,
  531. ARRAYSIZE(g_Options.szDescription),
  532. NULL );
  533. if ( !b )
  534. {
  535. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  536. ErrorBox( hDlg, szFilepath );
  537. goto Cleanup;
  538. }
  539. // if this hasn't been substituted from the strings section, then
  540. // do the lookup manually. to do this skip and remove the "%"s
  541. if (g_Options.szDescription[0] == L'%' &&
  542. g_Options.szDescription[wcslen(g_Options.szDescription)-1] == L'%') {
  543. g_Options.szDescription[wcslen(g_Options.szDescription)-1] = L'\0';
  544. wcscpy(szTemp,&g_Options.szDescription[1]);
  545. b = SetupFindFirstLine(
  546. hinf,
  547. L"Strings",
  548. szTemp,
  549. &context );
  550. if ( !b ) {
  551. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  552. ErrorBox( hDlg, szFilepath );
  553. goto Cleanup;
  554. }
  555. b = SetupGetStringField(
  556. &context,
  557. 1,
  558. g_Options.szDescription,
  559. ARRAYSIZE(g_Options.szDescription),
  560. NULL );
  561. if ( !b ) {
  562. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  563. ErrorBox( hDlg, szFilepath );
  564. goto Cleanup;
  565. }
  566. }
  567. DebugMsg( "Image Description: %s\n", g_Options.szDescription );
  568. b = SetupFindFirstLine( hinf, L"SetupData", L"DefaultPath", &context );
  569. if ( b )
  570. {
  571. b = SetupGetStringField(
  572. &context,
  573. 1,
  574. szTemp,
  575. ARRAYSIZE(szTemp),
  576. NULL );
  577. if (b) {
  578. PWSTR p;
  579. p = wcschr( szTemp, '\\');
  580. if (p) {
  581. p += 1;
  582. } else {
  583. p = szTemp;
  584. }
  585. wcscpy( g_Options.szInstallationName, p );
  586. DebugMsg( "Image Path: %s\n", g_Options.szInstallationName );
  587. }
  588. }
  589. }
  590. SetupCloseInfFile( hinf );
  591. //
  592. // build the path to layout.inf
  593. //
  594. wcscpy( szFilepath, g_Options.szSourcePath );
  595. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  596. ConcatenatePaths( szFilepath, L"layout.inf" );
  597. //
  598. // open the file
  599. //
  600. hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
  601. if ( hinf == INVALID_HANDLE_VALUE ) {
  602. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  603. ErrorBox( hDlg, szFilepath );
  604. goto Cleanup;
  605. }
  606. if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) {
  607. b = SetupFindFirstLine( hinf, L"SourceDisksNames.x86", L"1", &context );
  608. if ( !b )
  609. {
  610. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  611. ErrorBox( hDlg, szFilepath );
  612. goto Cleanup;
  613. }
  614. }
  615. if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ) {
  616. b = SetupFindFirstLine( hinf, L"SourceDisksNames.ia64", L"1", &context );
  617. if ( !b )
  618. {
  619. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  620. ErrorBox( hDlg, szFilepath );
  621. goto Cleanup;
  622. }
  623. }
  624. if ( b ) {
  625. b = SetupGetStringField( &context, 1, g_Options.szWorkstationDiscName, ARRAYSIZE(g_Options.szWorkstationDiscName), NULL );
  626. if ( !b )
  627. {
  628. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  629. ErrorBox( hDlg, szFilepath );
  630. goto Cleanup;
  631. }
  632. DebugMsg( "Workstation Disc Name: %s\n", g_Options.szWorkstationDiscName );
  633. b = SetupGetStringField( &context, 2, g_Options.szWorkstationTagFile, ARRAYSIZE(g_Options.szWorkstationTagFile), NULL );
  634. if ( !b )
  635. {
  636. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  637. ErrorBox( hDlg, szFilepath );
  638. goto Cleanup;
  639. }
  640. DebugMsg( "Workstation Tag File: %s\n", g_Options.szWorkstationTagFile);
  641. b = SetupGetStringField( &context, 4, g_Options.szWorkstationSubDir, ARRAYSIZE(g_Options.szWorkstationSubDir), NULL );
  642. if ( !b )
  643. {
  644. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  645. ErrorBox( hDlg, szFilepath );
  646. goto Cleanup;
  647. }
  648. DebugMsg( "Workstation Sub Dir: %s\n", g_Options.szWorkstationSubDir );
  649. }
  650. SetupCloseInfFile( hinf );
  651. hinf = INVALID_HANDLE_VALUE;
  652. //
  653. // build the path to setupp.ini
  654. //
  655. wcscpy( szFilepath, g_Options.szSourcePath );
  656. ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString);
  657. ConcatenatePaths( szFilepath, L"setupp.ini" );
  658. b = GetPrivateProfileStruct(L"Pid",
  659. L"ExtraData",
  660. szPidExtraData,
  661. sizeof(szPidExtraData),
  662. szFilepath);
  663. if ( !b )
  664. {
  665. MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_SETUP_INI_MISSING_OR_INVALID, MB_OK );
  666. hr = E_FAIL;
  667. goto Cleanup;
  668. }
  669. //
  670. // For a valid full (non-upgrade) PID, the fourth and sixth bytes
  671. // are odd.
  672. //
  673. if (((szPidExtraData[3] % 2) == 0) || ((szPidExtraData[5] % 2) == 0))
  674. {
  675. MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_UPGRADE_VERSION_NOT_SUPPORTED, MB_OK );
  676. hr = E_FAIL;
  677. goto Cleanup;
  678. }
  679. hr = S_OK;
  680. Cleanup:
  681. if ( hinf != INVALID_HANDLE_VALUE ) {
  682. SetupCloseInfFile( hinf );
  683. }
  684. HRETURN(hr);
  685. }
  686. HRESULT
  687. GetHelpAndDescriptionTextFromSif(
  688. OUT PWSTR HelpText,
  689. IN DWORD HelpTextSizeInChars,
  690. OUT PWSTR DescriptionText,
  691. IN DWORD DescriptionTextInChars
  692. )
  693. {
  694. WCHAR szSourcePath[MAX_PATH*2];
  695. WCHAR TempPath[MAX_PATH];
  696. WCHAR TempFile[MAX_PATH];
  697. HINF hInf;
  698. UINT uLineNum;
  699. HRESULT hr;
  700. INFCONTEXT context;
  701. PCWSTR szFileName = L"ristndrd.sif" ;
  702. //
  703. // Create the path to the default SIF file
  704. //
  705. wsprintf( szSourcePath,
  706. L"%s\\%s",
  707. g_Options.szSourcePath,
  708. szFileName );
  709. Assert( wcslen( szSourcePath ) < ARRAYSIZE(szSourcePath));
  710. if (GetTempPath(ARRAYSIZE(TempPath), TempPath) &&
  711. GetTempFileName(TempPath, L"RIS", 0, TempFile ) &&
  712. SetupDecompressOrCopyFile( szSourcePath, TempFile, NULL ) == ERROR_SUCCESS) {
  713. //
  714. // first try INF_STYLE_WIN4, and if that fails, then try
  715. // INF_STYLE_OLDNT (in case the inf doesn't have a [version] section.
  716. //
  717. hInf = SetupOpenInfFile( TempFile, NULL, INF_STYLE_WIN4, &uLineNum);
  718. if (hInf == INVALID_HANDLE_VALUE) {
  719. hInf = SetupOpenInfFile( TempFile, NULL, INF_STYLE_OLDNT, &uLineNum);
  720. if (hInf == INVALID_HANDLE_VALUE) {
  721. hr = HRESULT_FROM_WIN32(GetLastError());
  722. goto e1;
  723. }
  724. }
  725. if (!SetupFindFirstLine( hInf, L"OSChooser", L"Help", &context )) {
  726. hr = HRESULT_FROM_WIN32(GetLastError());
  727. goto e2;
  728. }
  729. if (!SetupGetStringField(
  730. &context,
  731. 1,
  732. HelpText,
  733. HelpTextSizeInChars,
  734. NULL )) {
  735. hr = HRESULT_FROM_WIN32(GetLastError());
  736. goto e2;
  737. }
  738. if (!SetupFindFirstLine( hInf, L"OSChooser", L"Description", &context )) {
  739. hr = HRESULT_FROM_WIN32(GetLastError());
  740. goto e2;
  741. }
  742. if (!SetupGetStringField(
  743. &context,
  744. 1,
  745. DescriptionText,
  746. DescriptionTextInChars,
  747. NULL )) {
  748. hr = HRESULT_FROM_WIN32(GetLastError());
  749. goto e2;
  750. }
  751. } else {
  752. hr = HRESULT_FROM_WIN32(GetLastError());
  753. goto e0;
  754. }
  755. hr = S_OK;
  756. e2:
  757. SetupCloseInfFile( hInf );
  758. e1:
  759. DeleteFile( TempFile );
  760. e0:
  761. return(hr);
  762. }
  763. //
  764. // CheckIntelliMirrorDrive( )
  765. //
  766. HRESULT
  767. CheckIntelliMirrorDrive(
  768. HWND hDlg )
  769. {
  770. TraceFunc( "CheckIntelliMirrorDrive( )\n" );
  771. HRESULT hr = S_OK;
  772. LONG lResult;
  773. BOOL b;
  774. DWORD dw;
  775. WCHAR sz[ MAX_PATH ];
  776. WCHAR szExpanded[ MAX_PATH ];
  777. WCHAR szBootDir[3];
  778. WCHAR szVolumePath[ MAX_PATH ];
  779. WCHAR szVolumeName[ MAX_PATH ];
  780. WCHAR szVolumePath2[ MAX_PATH ];
  781. WCHAR szVolumeName2[ MAX_PATH ];
  782. WCHAR szFileSystemType[ MAX_PATH ];
  783. UINT uDriveType;
  784. //
  785. // Get the real volume name for the target directory.
  786. //
  787. b = GetVolumePathName( g_Options.szIntelliMirrorPath, szVolumePath, ARRAYSIZE( szVolumePath ));
  788. if (b) {
  789. b = GetVolumeNameForVolumeMountPoint( szVolumePath, szVolumeName, ARRAYSIZE( szVolumeName ));
  790. }
  791. //
  792. // Make sure the device is not a removable media, CDROM, RamDisk, etc...
  793. // Only allow fixed disks.
  794. //
  795. if (b) {
  796. uDriveType = GetDriveType( szVolumeName );
  797. }
  798. if ( !b || (uDriveType != DRIVE_FIXED) )
  799. {
  800. MessageBoxFromStrings( hDlg,
  801. IDS_FIXEDDISK_CAPTION,
  802. IDS_FIXEDDISK_TEXT,
  803. MB_OK | MB_ICONSTOP );
  804. goto Error;
  805. }
  806. //
  807. // Get the real volume name for the system volume (%windir%).
  808. //
  809. // Get the default path which happens to be the
  810. // SystemDrive:\IntelliMirror
  811. //
  812. dw = LoadString( g_hinstance, IDS_DEFAULTPATH, sz, ARRAYSIZE( sz ));
  813. Assert( dw );
  814. dw = ExpandEnvironmentStrings( sz, szExpanded, ARRAYSIZE( sz ));
  815. Assert( dw );
  816. b = GetVolumePathName( szExpanded, szVolumePath2, ARRAYSIZE( szVolumePath2 ));
  817. Assert( b );
  818. b = GetVolumeNameForVolumeMountPoint( szVolumePath2, szVolumeName2, ARRAYSIZE( szVolumeName2 ));
  819. Assert( b );
  820. //
  821. // Don't let the target directory volume be the same as the system volume.
  822. //
  823. if ( StrCmpI( szVolumeName, szVolumeName2 ) == 0 )
  824. {
  825. MessageBoxFromStrings( hDlg,
  826. IDS_SAME_DRIVE_AS_SYSTEM_TITLE,
  827. IDS_SAME_DRIVE_AS_SYSTEM_MESSAGE,
  828. MB_OK | MB_ICONSTOP );
  829. goto Error;
  830. }
  831. #ifdef _X86_
  832. //
  833. // See if the system partition (the one with boot.ini on it)
  834. // is the drive the user has selected. We can't allow this
  835. // either since SIS might hide boot.ini.
  836. //
  837. b = x86DetermineSystemPartition( NULL, &szBootDir[0] );
  838. if ( !b )
  839. {
  840. szBootDir[0] = L'C';
  841. }
  842. szBootDir[1] = L':';
  843. szBootDir[2] = L'\\';
  844. b = GetVolumePathName( szBootDir, szVolumePath2, ARRAYSIZE( szVolumePath2 ));
  845. Assert( b );
  846. b = GetVolumeNameForVolumeMountPoint( szVolumePath2, szVolumeName2, ARRAYSIZE( szVolumeName2 ));
  847. Assert( b );
  848. //
  849. // Don't let the target directory volume be the same as the boot volume.
  850. //
  851. if ( StrCmpI( szVolumeName, szVolumeName2 ) == 0 )
  852. {
  853. MessageBoxFromStrings( hDlg,
  854. IDS_SAME_DRIVE_AS_BOOT_PARTITION_TITLE,
  855. IDS_SAME_DRIVE_AS_BOOT_PARTITION,
  856. MB_OK | MB_ICONSTOP );
  857. goto Error;
  858. }
  859. #endif
  860. //
  861. // Check to see if the IMirror directory will live on an NTFS
  862. // file system.
  863. //
  864. b = GetVolumeInformation( szVolumeName,
  865. NULL,
  866. 0,
  867. NULL,
  868. NULL,
  869. NULL,
  870. szFileSystemType,
  871. ARRAYSIZE( szFileSystemType ));
  872. if ( !b || StrCmpNI( szFileSystemType, L"NTFS", 4 ) != 0 ) {
  873. MessageBoxFromStrings( hDlg,
  874. IDS_SHOULD_BE_NTFS_TITLE,
  875. IDS_SHOULD_BE_NTFS_MESSAGE,
  876. MB_OK | MB_ICONSTOP );
  877. goto Error;
  878. }
  879. if ( 0xFFFFffff != GetFileAttributes( g_Options.szIntelliMirrorPath ) )
  880. {
  881. INT iResult = MessageBoxFromStrings( hDlg,
  882. IDS_DIRECTORYEXISTS_CAPTION,
  883. IDS_DIRECTORYEXISTS_TEXT,
  884. MB_YESNO | MB_ICONQUESTION );
  885. if ( iResult == IDNO )
  886. goto Error;
  887. }
  888. Cleanup:
  889. HRETURN(hr);
  890. Error:
  891. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 );
  892. hr = E_FAIL;
  893. goto Cleanup;
  894. }
  895. VOID
  896. ConcatenatePaths(
  897. IN OUT LPWSTR Path1,
  898. IN LPCWSTR Path2
  899. )
  900. {
  901. BOOL NeedBackslash = TRUE;
  902. DWORD l = wcslen( Path1 );
  903. //
  904. // Determine whether we need to stick a backslash between the components.
  905. //
  906. if ( (l != 0) && (Path1[l-1] == L'\\') ) {
  907. NeedBackslash = FALSE;
  908. }
  909. if ( *Path2 == L'\\' ) {
  910. if ( NeedBackslash ) {
  911. NeedBackslash = FALSE;
  912. } else {
  913. //
  914. // Not only do we not need a backslash, but we need to eliminate
  915. // one before concatenating.
  916. //
  917. Path2++;
  918. }
  919. }
  920. if ( NeedBackslash ) {
  921. wcscat( Path1, L"\\" );
  922. }
  923. wcscat( Path1, Path2 );
  924. return;
  925. }
  926. //
  927. // FindImageSource( )
  928. //
  929. HRESULT
  930. FindImageSource(
  931. HWND hDlg )
  932. {
  933. TraceFunc( "FindImageSource( )\n" );
  934. INT i;
  935. HANDLE hFile;
  936. WCHAR szFilePath[ MAX_PATH ];
  937. //
  938. // Look for txtsetup.sif where we think the files are located.
  939. // txtsetup.sif is in an architecture-specific subdirectory.
  940. //
  941. wcscpy( szFilePath, g_Options.szSourcePath );
  942. ConcatenatePaths( szFilePath, g_Options.ProcessorArchitectureString );
  943. ConcatenatePaths( szFilePath, L"\\txtsetup.sif" );
  944. hFile = CreateFile( szFilePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
  945. if ( hFile != INVALID_HANDLE_VALUE )
  946. {
  947. CloseHandle( hFile );
  948. HRETURN(S_OK);
  949. }
  950. HRETURN( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) );
  951. }
  952. HRESULT
  953. GetSetRanFlag(
  954. BOOL bQuery,
  955. BOOL bClear
  956. )
  957. /*++
  958. Routine Description:
  959. Set's or Get's the state of a registry flag that indicates setup has been
  960. run before.
  961. Arguments:
  962. bQuery - if TRUE, indicates that the registry flag should be queried
  963. bClear - only valid if bQuery is FALSE. If this parameter is TRUE,
  964. it indicates that the flag should be set to the cleared state.
  965. FALSE indicates that the flag should be set.
  966. Return Value:
  967. HRESULT indicating outcome.
  968. --*/
  969. {
  970. LONG lResult;
  971. HKEY hkeySetup;
  972. HRESULT Result = E_FAIL;
  973. lResult = RegOpenKeyEx(
  974. HKEY_LOCAL_MACHINE,
  975. L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
  976. 0,
  977. bQuery
  978. ? KEY_QUERY_VALUE
  979. : KEY_SET_VALUE,
  980. &hkeySetup);
  981. if ( lResult == ERROR_SUCCESS ) {
  982. DWORD dwValue = (bClear == FALSE) ? 1 : 0;
  983. DWORD cbValue = sizeof(dwValue);
  984. DWORD type;
  985. if (bQuery) {
  986. lResult = RegQueryValueEx( hkeySetup, L"RemInst", NULL, &type, (LPBYTE)&dwValue, &cbValue );
  987. if (lResult == ERROR_SUCCESS) {
  988. Result = (dwValue == 1)
  989. ? S_OK
  990. : E_FAIL;
  991. } else {
  992. Result = HRESULT_FROM_WIN32(lResult);
  993. }
  994. } else {
  995. lResult = RegSetValueEx( hkeySetup, L"RemInst", NULL, REG_DWORD, (LPBYTE)&dwValue, cbValue );
  996. Result = HRESULT_FROM_WIN32(lResult);
  997. }
  998. RegCloseKey( hkeySetup );
  999. } else {
  1000. Result = HRESULT_FROM_WIN32(lResult);
  1001. }
  1002. return(Result);
  1003. }
  1004. //
  1005. // GetNtVersionInfo( )
  1006. //
  1007. // Retrieves the build version from the kernel
  1008. //
  1009. BOOLEAN
  1010. GetBuildNumberFromImagePath(
  1011. PDWORD pdwVersion,
  1012. PCWSTR SearchDir,
  1013. PCWSTR SubDir OPTIONAL
  1014. )
  1015. {
  1016. DWORD Error = ERROR_SUCCESS;
  1017. DWORD FileVersionInfoSize;
  1018. DWORD VersionHandle;
  1019. ULARGE_INTEGER TmpVersion;
  1020. PVOID VersionInfo;
  1021. VS_FIXEDFILEINFO * FixedFileInfo;
  1022. UINT FixedFileInfoLength;
  1023. WCHAR Path[MAX_PATH];
  1024. BOOLEAN fResult = FALSE;
  1025. TraceFunc("GetNtVersionInfo( )\n");
  1026. *pdwVersion = 0;
  1027. //
  1028. // build a path to the kernel
  1029. //
  1030. // Resulting string should be something like:
  1031. // "\\server\reminst\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
  1032. //
  1033. if (!SearchDir) {
  1034. goto e0;
  1035. }
  1036. wcscpy(Path, SearchDir);
  1037. if (SubDir) {
  1038. ConcatenatePaths( Path, SubDir );
  1039. }
  1040. ConcatenatePaths( Path, L"ntkrnlmp.exe");
  1041. //
  1042. // need to expand this file to local location to crack it
  1043. //
  1044. FileVersionInfoSize = GetFileVersionInfoSize(Path, &VersionHandle);
  1045. if (FileVersionInfoSize == 0)
  1046. goto e0;
  1047. VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize );
  1048. if (VersionInfo == NULL)
  1049. goto e0;
  1050. if (!GetFileVersionInfo(
  1051. Path,
  1052. VersionHandle,
  1053. FileVersionInfoSize,
  1054. VersionInfo))
  1055. goto e1;
  1056. if (!VerQueryValue(
  1057. VersionInfo,
  1058. L"\\",
  1059. (LPVOID*)&FixedFileInfo,
  1060. &FixedFileInfoLength))
  1061. goto e1;
  1062. TmpVersion.HighPart = FixedFileInfo->dwFileVersionMS;
  1063. TmpVersion.LowPart = FixedFileInfo->dwFileVersionLS;
  1064. *pdwVersion = HIWORD(FixedFileInfo->dwFileVersionLS);
  1065. fResult = TRUE;
  1066. e1:
  1067. LocalFree( VersionInfo );
  1068. e0:
  1069. RETURN( fResult );
  1070. }
  1071. VOID
  1072. GetProcessorType(
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This function will pre-populate the g_Options.ProcessorArchitectureString variable
  1077. with a default value. This value is based on the processor
  1078. architecture we're currently running on.
  1079. We'll use this value to determine which backing file should
  1080. be used to generate the remote install flat image on the
  1081. server.
  1082. Arguments:
  1083. None.
  1084. Return Value:
  1085. None.
  1086. --*/
  1087. {
  1088. SYSTEM_INFO si;
  1089. if( g_Options.ProcessorArchitectureString[0] == TEXT('\0') ) {
  1090. //
  1091. // We haven't been initialized yet.
  1092. //
  1093. GetSystemInfo( &si );
  1094. switch (si.wProcessorArchitecture) {
  1095. case PROCESSOR_ARCHITECTURE_IA64:
  1096. g_Options.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
  1097. wcscpy( g_Options.ProcessorArchitectureString, L"ia64" );
  1098. break;
  1099. //
  1100. // if we get here, assume it's x86
  1101. //
  1102. default:
  1103. g_Options.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  1104. wcscpy( g_Options.ProcessorArchitectureString, L"i386" );
  1105. break;
  1106. }
  1107. }
  1108. }