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.

796 lines
22 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // scsi.c
  8. //
  9. // Description:
  10. // This file contains the dialog procedure for the SCSI files.
  11. // (IDD_SCSI).
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "pch.h"
  15. #include "resource.h"
  16. #define MAX_SCSI_SELECTIONS 1024
  17. #define MAX_SCSI_NAME_LEN 256
  18. #define SCSI_FILE_EXTENSION _T("oem")
  19. #define ALL_FILE_EXTENSION _T("*")
  20. static TCHAR* StrScsiFiles;
  21. static TCHAR* StrAllFiles;
  22. static TCHAR g_szScsiFileFilter[MAX_PATH + 1];
  23. static TCHAR g_szAllFileFilter[MAX_PATH + 1];
  24. //
  25. // This var keeps track of the path to the txtsetup.oem
  26. //
  27. static TCHAR szTxtSetupOemLocation[MAX_PATH];
  28. //
  29. // This var keeps track of if the user has loaded a new txtsetup.oem so we
  30. // know when we need to copy more files over.
  31. //
  32. static BOOL bHasLoadedTxtSetupOem = FALSE;
  33. VOID LoadOriginalSettingsLowHalScsi(HWND hwnd,
  34. LPTSTR lpFileName,
  35. QUEUENUM dwWhichQueue);
  36. static VOID LoadScsiFromTxtsetupOem( IN HWND hwnd,
  37. IN TCHAR *szTxtSetupOemPath );
  38. //----------------------------------------------------------------------------
  39. //
  40. // Function: OnScsiInitDialog
  41. //
  42. // Purpose:
  43. //
  44. // Arguments: HWND hwnd - handle to the dialog box
  45. //
  46. // Returns: VOID
  47. //
  48. //----------------------------------------------------------------------------
  49. static VOID
  50. OnScsiInitDialog( IN HWND hwnd )
  51. {
  52. HRESULT hrPrintf;
  53. //
  54. // Load the resource strings
  55. //
  56. StrScsiFiles = MyLoadString( IDS_SCSI_FILES );
  57. StrAllFiles = MyLoadString( IDS_ALL_FILES );
  58. //
  59. // Build the text file filter string
  60. //
  61. //
  62. // The question marks (?) are just placehoders for where the NULL char
  63. // will be inserted.
  64. //
  65. hrPrintf=StringCchPrintf( g_szScsiFileFilter,AS(g_szScsiFileFilter),
  66. _T("%s (*.oem)?*.oem?%s (*.*)?*.*?"),
  67. StrScsiFiles,
  68. StrAllFiles );
  69. ConvertQuestionsToNull( g_szScsiFileFilter );
  70. hrPrintf=StringCchPrintf( g_szAllFileFilter, AS(g_szAllFileFilter),
  71. _T("%s (*.*)?*.*?"),
  72. StrAllFiles );
  73. ConvertQuestionsToNull( g_szAllFileFilter );
  74. }
  75. //----------------------------------------------------------------------------
  76. //
  77. // Function: OnScsiSetActive
  78. //
  79. // Purpose:
  80. //
  81. // Arguments: HWND hwnd - handle to the dialog box
  82. //
  83. // Returns: VOID
  84. //
  85. //----------------------------------------------------------------------------
  86. static VOID
  87. OnScsiSetActive( IN HWND hwnd ) {
  88. INT_PTR i;
  89. INT_PTR iListBoxCount;
  90. TCHAR szListBoxEntryText[MAX_STRING_LEN];
  91. //
  92. // If we are editing a script and haven't loaded the txtsetup.oem, then
  93. // populate the list box with the entries in the txtsetup.oem
  94. //
  95. if( ! WizGlobals.bNewScript && ! bHasLoadedTxtSetupOem ) {
  96. //
  97. // The OEM files path must be valid if we are going to use it to
  98. // read files.
  99. //
  100. AssertMsg( WizGlobals.OemFilesPath[0] != _T('\0'),
  101. "OEM files path is blank");
  102. //
  103. // Populate the list box with the SCSI entries in txtsetup.oem
  104. //
  105. ConcatenatePaths( szTxtSetupOemLocation,
  106. WizGlobals.OemFilesPath,
  107. _T("Textmode"),
  108. NULL );
  109. LoadScsiFromTxtsetupOem( hwnd, szTxtSetupOemLocation );
  110. //
  111. // Select those entries in the MassStorageDrivers namelist
  112. //
  113. iListBoxCount = SendDlgItemMessage( hwnd,
  114. IDC_LB_SCSI,
  115. LB_GETCOUNT,
  116. 0,
  117. 0 );
  118. //
  119. // For each entry in the list box, see if its name is in the namelist
  120. // and if it is, then select it.
  121. //
  122. for( i = 0; i < iListBoxCount; i++ ) {
  123. SendDlgItemMessage( hwnd,
  124. IDC_LB_SCSI,
  125. LB_GETTEXT,
  126. i,
  127. (LPARAM) szListBoxEntryText );
  128. if( FindNameInNameList( &GenSettings.MassStorageDrivers,
  129. szListBoxEntryText ) != -1 ) {
  130. SendDlgItemMessage( hwnd,
  131. IDC_LB_SCSI,
  132. LB_SETSEL,
  133. TRUE,
  134. i );
  135. }
  136. }
  137. }
  138. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | PSWIZB_NEXT);
  139. }
  140. //----------------------------------------------------------------------------
  141. //
  142. // Function: LoadScsiFromTxtsetupOem
  143. //
  144. // Purpose: Reads the txtsetup.oem in the specified parameter and load the
  145. // SCSI choices into the list box.
  146. //
  147. // Arguments: hwnd - handle to the dialog box
  148. // szTxtSetupOemPath - path to the txtsetup.oem
  149. //
  150. // Returns: VOID
  151. //
  152. //----------------------------------------------------------------------------
  153. static VOID
  154. LoadScsiFromTxtsetupOem( IN HWND hwnd,
  155. IN TCHAR *szTxtSetupOemPath ) {
  156. INT_PTR iIndex;
  157. BOOL bKeepReading;
  158. TCHAR szTxtSetupOemPathAndFilename[MAX_PATH] = _T("");
  159. TCHAR szScsiDriverName[MAX_SCSI_NAME_LEN] = _T("");
  160. TCHAR szScsiFriendlyName[MAX_SCSI_NAME_LEN] = _T("");
  161. HINF hScsiOem;
  162. INFCONTEXT ScsiOemContext = { 0 };
  163. ConcatenatePaths( szTxtSetupOemPathAndFilename,
  164. szTxtSetupOemPath,
  165. OEM_TXTSETUP_NAME,
  166. NULL );
  167. hScsiOem = SetupOpenInfFile( szTxtSetupOemPathAndFilename,
  168. NULL,
  169. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  170. NULL );
  171. if( hScsiOem == INVALID_HANDLE_VALUE ) {
  172. // ISSUE-2002/02/28-stelo- alert an error that we couldn't open the file
  173. return;
  174. }
  175. ScsiOemContext.Inf = hScsiOem;
  176. ScsiOemContext.CurrentInf = hScsiOem;
  177. bKeepReading = SetupFindFirstLine( hScsiOem,
  178. _T("SCSI"),
  179. NULL,
  180. &ScsiOemContext );
  181. //
  182. // For each SCSI entry, add its friendly-name to the list box
  183. //
  184. while( bKeepReading ) {
  185. TCHAR *pScsiDriverName;
  186. SetupGetStringField( &ScsiOemContext,
  187. 0,
  188. szScsiDriverName,
  189. MAX_SCSI_NAME_LEN,
  190. NULL );
  191. SetupGetStringField( &ScsiOemContext,
  192. 1,
  193. szScsiFriendlyName,
  194. MAX_SCSI_NAME_LEN,
  195. NULL );
  196. //
  197. // Don't allow the adding of a blank name (protection against a bad input file)
  198. //
  199. if( szScsiFriendlyName[0] != _T('\0') ) {
  200. iIndex = SendDlgItemMessage( hwnd,
  201. IDC_LB_SCSI,
  202. LB_ADDSTRING,
  203. 0,
  204. (LPARAM) szScsiFriendlyName );
  205. pScsiDriverName = (TCHAR*) malloc( sizeof(szScsiDriverName) );
  206. if (pScsiDriverName == NULL)
  207. TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
  208. lstrcpyn( pScsiDriverName, szScsiDriverName, AS(szScsiDriverName));
  209. SendDlgItemMessage( hwnd,
  210. IDC_LB_SCSI,
  211. LB_SETITEMDATA,
  212. iIndex,
  213. (LPARAM) pScsiDriverName );
  214. }
  215. //
  216. // move to the next line of the .oem file
  217. //
  218. bKeepReading = SetupFindNextLine( &ScsiOemContext, &ScsiOemContext );
  219. }
  220. SetupCloseInfFile( hScsiOem );
  221. bHasLoadedTxtSetupOem = TRUE;
  222. }
  223. //----------------------------------------------------------------------------
  224. //
  225. // Function: ClearScsiListBox
  226. //
  227. // Purpose: Deallocates memory for all the elements in the SCSI list box and
  228. // clears it.
  229. //
  230. // Arguments: HWND hwnd - handle to the dialog box
  231. //
  232. // Returns: VOID
  233. //
  234. //----------------------------------------------------------------------------
  235. static VOID
  236. ClearScsiListBox( IN HWND hwnd ) {
  237. INT_PTR i;
  238. INT_PTR iListBoxCount;
  239. TCHAR *pData;
  240. iListBoxCount = SendDlgItemMessage( hwnd,
  241. IDC_LB_SCSI,
  242. LB_GETCOUNT,
  243. 0,
  244. 0 );
  245. for( i = 0; i < iListBoxCount; i++ ) {
  246. pData = (TCHAR *) SendDlgItemMessage( hwnd,
  247. IDC_LB_SCSI,
  248. LB_GETITEMDATA,
  249. i,
  250. 0 );
  251. if( pData ) {
  252. free( pData );
  253. }
  254. }
  255. SendDlgItemMessage( hwnd,
  256. IDC_LB_SCSI,
  257. LB_RESETCONTENT,
  258. 0,
  259. 0 );
  260. }
  261. //----------------------------------------------------------------------------
  262. //
  263. // Function: OnBrowseLoadDriver
  264. //
  265. // Purpose: Creates a browse window for the user to select an OEM driver and
  266. // populates the SCSI list box with the appropriate values
  267. //
  268. // NOTE: the malloc call in here is arguably a bug (memory leak). I
  269. // malloc the memory but never free it. Every malloc they do will be
  270. // <= MAX_PATH and realistically they won't do that many. Once they do
  271. // a load, if they do another load, I free the old memory (see
  272. // ClearScsiListBox) and allocate new memory. So, for the last load
  273. // they do, the memory never gets freed. To do it right,
  274. // we would free the memory at the end of the program but NT does this for
  275. // us anyways when the process gets killed. (so no need to free)
  276. //
  277. // Arguments: HWND hwnd - handle to the dialog box
  278. //
  279. // Returns: VOID
  280. //
  281. //----------------------------------------------------------------------------
  282. static VOID
  283. OnBrowseLoadDriver( IN HWND hwnd ) {
  284. INT iIndex;
  285. BOOL bKeepReading;
  286. BOOL bFileNotFound = TRUE;
  287. TCHAR szTxtSetupOemLocationAndFilename[MAX_PATH] = _T("");
  288. TCHAR szScsiFriendlyName[MAX_SCSI_NAME_LEN] = _T("");
  289. HINF hScsiOem = NULL;
  290. INFCONTEXT ScsiOemContext = { 0 };
  291. TCHAR PathBuffer[MAX_PATH];
  292. INT iRet;
  293. LPTSTR pFileName;
  294. GetCurrentDirectory( MAX_PATH, PathBuffer );
  295. ConcatenatePaths( szTxtSetupOemLocationAndFilename,
  296. szTxtSetupOemLocation,
  297. OEM_TXTSETUP_NAME,
  298. NULL );
  299. //
  300. // Keep asking for a file until we either get a txtsetup.oem or the user
  301. // presses cancel.
  302. //
  303. while( bFileNotFound ) {
  304. iRet = ShowBrowseFolder( hwnd,
  305. g_szScsiFileFilter,
  306. SCSI_FILE_EXTENSION,
  307. OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
  308. PathBuffer,
  309. szTxtSetupOemLocationAndFilename );
  310. if ( ! iRet )
  311. return; // user pressed cancel on the dialog
  312. pFileName = MyGetFullPath( szTxtSetupOemLocationAndFilename );
  313. if( pFileName && (LSTRCMPI( pFileName, OEM_TXTSETUP_NAME ) == 0) ) {
  314. bFileNotFound = FALSE; // we have found the file
  315. }
  316. else {
  317. // ISSUE-2002/02/28-stelo-
  318. /*
  319. ReportErrorId(hwnd,
  320. MSGTYPE_ERR | MSGTYPE_WIN32,
  321. ,
  322. GenSettings.lpszLogoBitmap, szLogoDestination);
  323. */
  324. }
  325. }
  326. ClearScsiListBox( hwnd );
  327. //
  328. // Trim the file name off szTxtSetupOemLocationAndFilename so it only
  329. // provides the path to the txtsetup.oem
  330. //
  331. {
  332. TCHAR *p = szTxtSetupOemLocationAndFilename;
  333. while( p != pFileName )
  334. {
  335. p++;
  336. }
  337. *p = _T('\0');
  338. }
  339. lstrcpyn( szTxtSetupOemLocation, szTxtSetupOemLocationAndFilename, AS(szTxtSetupOemLocation) );
  340. //
  341. // Read in from the file OEM file they specified in the browse box and
  342. // add the friendly-name entries to the list box
  343. //
  344. LoadScsiFromTxtsetupOem( hwnd, szTxtSetupOemLocation );
  345. }
  346. //----------------------------------------------------------------------------
  347. //
  348. // Function: CopyFileToDistShare
  349. //
  350. // Purpose: Given a path and file name to one file, it copies that file to
  351. // the given destination path. If the file already exists on the
  352. // destination, then do not make the copy. If the source file name does
  353. // not exist then Browse for it.
  354. //
  355. // Arguments:
  356. // HWND hwnd - handle to the dialog box
  357. // LPTSTR szSrcPath - path file to copy
  358. // LPTSTR szSrcFileName - filename to copy
  359. // LPTSTR szDestPath - path of where file is to be copied
  360. //
  361. // Returns: VOID
  362. //
  363. //----------------------------------------------------------------------------
  364. VOID
  365. CopyFileToDistShare( IN HWND hwnd,
  366. IN LPTSTR szSrcPath,
  367. IN LPTSTR szSrcFileName,
  368. IN LPTSTR szDestPath ) {
  369. INT iRet;
  370. TCHAR szSrcPathAndName[MAX_PATH] = _T("");
  371. TCHAR szDestPathAndName[MAX_PATH] = _T("");
  372. ConcatenatePaths( szSrcPathAndName,
  373. szSrcPath,
  374. szSrcFileName,
  375. NULL );
  376. ConcatenatePaths( szDestPathAndName,
  377. szDestPath,
  378. szSrcFileName,
  379. NULL );
  380. if( ! DoesFileExist( szSrcPathAndName ) )
  381. {
  382. TCHAR* pFileName;
  383. BOOL bFileFound = FALSE;
  384. do
  385. {
  386. ReportErrorId( hwnd,
  387. MSGTYPE_ERR,
  388. IDS_ERR_SPECIFY_FILE,
  389. szSrcFileName );
  390. iRet = ShowBrowseFolder( hwnd,
  391. g_szAllFileFilter,
  392. ALL_FILE_EXTENSION,
  393. OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
  394. szSrcPath,
  395. szSrcPathAndName );
  396. // ISSUE-2002/02/28-stelo- if they press cancel should I warn them that they have to
  397. // copy the file manually?
  398. if ( ! iRet )
  399. return; // user pressed cancel on the dialog
  400. pFileName = MyGetFullPath( szSrcPathAndName );
  401. if( pFileName && ( lstrcmpi( pFileName, szSrcFileName ) == 0 ) ) {
  402. bFileFound = TRUE; // we have found the file
  403. }
  404. } while( ! bFileFound );
  405. }
  406. CopyFile( szSrcPathAndName, szDestPathAndName, TRUE );
  407. SetFileAttributes( szDestPathAndName, FILE_ATTRIBUTE_NORMAL );
  408. }
  409. //----------------------------------------------------------------------------
  410. //
  411. // Function: OnWizNextScsi
  412. //
  413. // Purpose: For every selection in the SCSI list box, copy the files over to
  414. // the distribution share and stores the driver and filenames so they can
  415. // be written out.
  416. //
  417. // Arguments: IN HWND hwnd - handle to the dialog box
  418. //
  419. // Returns: VOID
  420. //
  421. //----------------------------------------------------------------------------
  422. VOID
  423. OnWizNextScsi( IN HWND hwnd ) {
  424. INT_PTR i;
  425. INT_PTR iNumberSelected;
  426. BOOL bKeepReading;
  427. UINT rgiScsiSelections[MAX_SCSI_SELECTIONS];
  428. TCHAR *pDriverName;
  429. TCHAR szDriverSectionName[MAX_INILINE_LEN];
  430. TCHAR szScsiDriverName[MAX_SCSI_NAME_LEN];
  431. TCHAR szTextmodePath[MAX_PATH] = _T("");
  432. TCHAR szOemFilePathAndName[MAX_PATH] = _T("");
  433. HINF hScsiOem;
  434. INFCONTEXT ScsiOemContext = { 0 };
  435. //
  436. // If they never loaded a txtsetup.oem, then there is no work to do
  437. //
  438. if( bHasLoadedTxtSetupOem == FALSE ) {
  439. return;
  440. }
  441. iNumberSelected = SendDlgItemMessage( hwnd,
  442. IDC_LB_SCSI,
  443. LB_GETSELITEMS,
  444. MAX_SCSI_SELECTIONS,
  445. (LPARAM) rgiScsiSelections );
  446. //
  447. // Prepare to add the new drivers
  448. //
  449. ResetNameList( &GenSettings.MassStorageDrivers );
  450. ConcatenatePaths( szTextmodePath,
  451. WizGlobals.OemFilesPath,
  452. _T("Textmode"),
  453. NULL );
  454. if ( ! EnsureDirExists( szTextmodePath ) )
  455. {
  456. ReportErrorId( hwnd,
  457. MSGTYPE_ERR | MSGTYPE_WIN32,
  458. IDS_ERR_CREATE_FOLDER,
  459. szTextmodePath );
  460. return;
  461. }
  462. ConcatenatePaths( szOemFilePathAndName,
  463. szTxtSetupOemLocation,
  464. OEM_TXTSETUP_NAME,
  465. NULL );
  466. //
  467. // Read the txtsetup.oem file into the txtsetup queue
  468. //
  469. LoadOriginalSettingsLowHalScsi(hwnd,
  470. szOemFilePathAndName,
  471. SETTING_QUEUE_TXTSETUP_OEM);
  472. hScsiOem = SetupOpenInfFile( szOemFilePathAndName,
  473. NULL,
  474. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  475. NULL );
  476. if( hScsiOem == INVALID_HANDLE_VALUE ) {
  477. // ISSUE-2002/02/28-stelo- need to somehow alert an error
  478. return;
  479. }
  480. for( i = 0; i < iNumberSelected; i++ ) {
  481. SendDlgItemMessage( hwnd,
  482. IDC_LB_SCSI,
  483. LB_GETTEXT,
  484. rgiScsiSelections[i],
  485. (LPARAM) szScsiDriverName );
  486. AddNameToNameList( &GenSettings.MassStorageDrivers,
  487. szScsiDriverName );
  488. ScsiOemContext.Inf = hScsiOem;
  489. ScsiOemContext.CurrentInf = hScsiOem;
  490. pDriverName = (TCHAR *) SendDlgItemMessage( hwnd,
  491. IDC_LB_SCSI,
  492. LB_GETITEMDATA,
  493. rgiScsiSelections[i],
  494. 0 );
  495. //
  496. // Build up the section name
  497. //
  498. lstrcpyn( szDriverSectionName, _T("Files.SCSI."), AS(szDriverSectionName));
  499. lstrcatn( szDriverSectionName, pDriverName, MAX_INILINE_LEN );
  500. bKeepReading = SetupFindFirstLine( hScsiOem,
  501. szDriverSectionName,
  502. NULL,
  503. &ScsiOemContext );
  504. //
  505. // For the [File.SCSI.x] entry, add its filenames to the OemScsiFiles
  506. // namelist and copy the files to the $oem$ dir
  507. //
  508. while( bKeepReading ) {
  509. SetupGetStringField( &ScsiOemContext,
  510. 2,
  511. szScsiDriverName,
  512. MAX_SCSI_NAME_LEN,
  513. NULL );
  514. //
  515. // Don't allow the adding of a blank name (protection against a bad
  516. // input file)
  517. //
  518. if( szScsiDriverName[0] != _T('\0') ) {
  519. //
  520. // Only copy the file if we haven't copied it already, this
  521. // could happen if 2 friendly-name drivers are selected and they
  522. // both use the same file.
  523. //
  524. if( FindNameInNameList( &GenSettings.OemScsiFiles,
  525. szScsiDriverName ) == NOT_FOUND ) {
  526. AddNameToNameList( &GenSettings.OemScsiFiles,
  527. szScsiDriverName );
  528. CopyFileToDistShare( hwnd,
  529. szTxtSetupOemLocation,
  530. szScsiDriverName,
  531. szTextmodePath );
  532. }
  533. }
  534. //
  535. // move to the next line of the .oem file
  536. //
  537. bKeepReading = SetupFindNextLine( &ScsiOemContext, &ScsiOemContext );
  538. }
  539. }
  540. SetupCloseInfFile( hScsiOem );
  541. }
  542. //----------------------------------------------------------------------------
  543. //
  544. // Function: DlgScsiPage
  545. //
  546. // Purpose: Dialog procedure for the SCSI driver page (Mass Storage devices).
  547. //
  548. // Arguments: standard Win32 dialog proc arguments
  549. //
  550. // Returns: standard Win32 dialog proc return value -- whether the message
  551. // was handled or not
  552. //
  553. //----------------------------------------------------------------------------
  554. INT_PTR CALLBACK
  555. DlgScsiPage( IN HWND hwnd,
  556. IN UINT uMsg,
  557. IN WPARAM wParam,
  558. IN LPARAM lParam )
  559. {
  560. BOOL bStatus = TRUE;
  561. switch( uMsg )
  562. {
  563. case WM_INITDIALOG:
  564. {
  565. OnScsiInitDialog( hwnd );
  566. break;
  567. }
  568. case WM_COMMAND: {
  569. switch ( LOWORD(wParam) )
  570. {
  571. case IDC_BUT_LOAD_DRIVER:
  572. if ( HIWORD(wParam) == BN_CLICKED )
  573. OnBrowseLoadDriver( hwnd );
  574. break;
  575. default:
  576. bStatus = FALSE;
  577. break;
  578. }
  579. break;
  580. }
  581. case WM_NOTIFY: {
  582. LPNMHDR pnmh = (LPNMHDR)lParam;
  583. switch( pnmh->code ) {
  584. case PSN_QUERYCANCEL:
  585. CancelTheWizard(hwnd); break;
  586. case PSN_SETACTIVE: {
  587. OnScsiSetActive( hwnd );
  588. break;
  589. }
  590. case PSN_WIZBACK:
  591. break;
  592. case PSN_WIZNEXT:
  593. OnWizNextScsi( hwnd );
  594. break;
  595. default:
  596. break;
  597. }
  598. break;
  599. }
  600. default:
  601. bStatus = FALSE;
  602. break;
  603. }
  604. return( bStatus );
  605. }