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.

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