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.

732 lines
21 KiB

  1. /**************************************************************************
  2. *
  3. * FILECOPY.C
  4. *
  5. * Copyright (C) Microsoft, 1990, All Rights Reserved.
  6. *
  7. * Control Panel Applet for installing installable driver.
  8. *
  9. * This file contains hooks to SULIB, COMPRESS libraries, and the dialogs
  10. * from the display applet to prompt for insert disk, error action...
  11. *
  12. * Note SULIB.LIB, COMPRESS.LIB, SULIB.H come from the display applet
  13. * and are updated here if/when updated there.
  14. *
  15. * History:
  16. *
  17. * Sat Oct 27 1990 -by- MichaelE
  18. * Munged from display applet's DLG.C.
  19. *
  20. **************************************************************************/
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include <string.h>
  24. #include "drivers.h"
  25. #include "sulib.h"
  26. #include <cphelp.h>
  27. // Hidden parameter between wsSingleCopyStatus and wExistDlg
  28. static char szErrMsg[MAXSTR];
  29. // Hidden parameters passed from wsInsertDisk to wDiskDlg
  30. static char CurrentDisk[MAX_PATH];
  31. static LPSTR szEdit;
  32. // Function prototypes
  33. BOOL wsInfParseInit (void);
  34. int fDialog (int, HWND, DLGPROC);
  35. UINT wsCopyError (int, LPSTR);
  36. UINT wsInsertDisk (LPSTR, LPSTR);
  37. BOOL wsDiskDlg (HWND, UINT, WPARAM, LPARAM);
  38. BOOL wsExistDlg (HWND, UINT, WPARAM, LPARAM);
  39. /*
  40. * Load the description from the inf file or the driver file.
  41. *
  42. * The type of file is also returned in the driver structure.
  43. *
  44. * Parameters :
  45. * pIDriver - Pointer to driver data - in particular the driver file name
  46. * pstrKey - The ini file key under which the driver should be found
  47. * pstrDesc - Where to return the description
  48. */
  49. int LoadDesc(PIDRIVER pIDriver, PSTR pstrKey, PSTR pstrDesc)
  50. {
  51. PINF pinf;
  52. CHAR szFileName[MAX_INF_LINE_LEN];
  53. PSTR pstrFile = pIDriver->szFile;
  54. CHAR ExpandedName[MAX_PATH];
  55. PSTR FilePart;
  56. /*
  57. * See if the file can be found
  58. */
  59. if (SearchPath(NULL, pstrFile, NULL, MAX_PATH, ExpandedName, &FilePart)
  60. == 0) {
  61. return(DESC_NOFILE);
  62. }
  63. /*
  64. * -jyg- Let's look in the mmdriver.inf first!
  65. */
  66. for (pinf = FindInstallableDriversSection(NULL);
  67. pinf;
  68. pinf = infNextLine(pinf))
  69. {
  70. infParseField(pinf, 1, szFileName); // compare filename
  71. /*
  72. * FileName strips of drive and path
  73. */
  74. if (lstrcmpi(FileName(pstrFile), FileName(szFileName)) == 0)
  75. {
  76. infParseField(pinf, 3, pstrDesc); // get Description Field
  77. return DESC_INF;
  78. }
  79. }
  80. /*
  81. * If that failed try to get the description from the file
  82. */
  83. if (!GetFileTitle(ExpandedName, pstrDesc, MAXSTR)) {
  84. return DESC_EXE;
  85. } else {
  86. return DESC_NOFILE;
  87. }
  88. }
  89. /*
  90. * Find the install path from the registry if there is one there
  91. */
  92. BOOL GetInstallPath(LPSTR szDirOfSrc)
  93. {
  94. HKEY RegHandle;
  95. DWORD Type;
  96. DWORD Length = MAX_PATH - 1;
  97. BOOL Found = FALSE;
  98. if (MMSYSERR_NOERROR ==
  99. RegOpenKey(HKEY_LOCAL_MACHINE,
  100. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"),
  101. &RegHandle)) {
  102. if (MMSYSERR_NOERROR ==
  103. RegQueryValueEx(RegHandle,
  104. TEXT("SourcePath"),
  105. NULL,
  106. &Type,
  107. szDirOfSrc,
  108. &Length) &&
  109. Type == REG_SZ) {
  110. Found = TRUE;
  111. }
  112. RegCloseKey(RegHandle);
  113. }
  114. return Found;
  115. }
  116. /*
  117. * Initialize the SULIB library stuff which loads the mmdriver.inf file
  118. * into RAM and parses it all over the place.
  119. */
  120. BOOL wsInfParseInit(void)
  121. {
  122. OFSTRUCT os;
  123. PINF pinf;
  124. char szNoInf[MAXSTR];
  125. int iDrive;
  126. static BOOL bChkCDROM = FALSE;
  127. /*
  128. * put up an hour glass here
  129. */
  130. wsStartWait();
  131. if (OpenFile(szSetupInf, &os, OF_EXIST) == -1) {
  132. wsEndWait();
  133. LoadString(myInstance, IDS_NOINF, szNoInf, sizeof(szNoInf));
  134. MessageBox(hMesgBoxParent, szNoInf, szDrivers, MB_OK | MB_ICONEXCLAMATION);
  135. return FALSE;
  136. }
  137. pinf = infOpen(os.szPathName);
  138. wsEndWait();
  139. GetWindowsDirectory(szSetupPath, sizeof(szSetupPath));
  140. if (bChkCDROM == FALSE) {
  141. /*
  142. * Use the setup path from the registry if there is one
  143. */
  144. if (!GetInstallPath(szDirOfSrc))
  145. {
  146. /*
  147. * use the CD ROM drive as the default drive (if there is one)
  148. */
  149. for ( iDrive='A'; iDrive <= 'Z'; iDrive++ ) {
  150. szDirOfSrc[0] = iDrive;
  151. if ( GetDriveType(szDirOfSrc) == DRIVE_CDROM)
  152. {
  153. break;
  154. }
  155. /*
  156. * If we didn't find a CD ROM default to the A drive
  157. */
  158. if (iDrive == 'Z') {
  159. szDirOfSrc[0] = 'A';
  160. }
  161. }
  162. }
  163. bChkCDROM = TRUE;
  164. }
  165. lstrcpy(szDiskPath, szDirOfSrc);
  166. return TRUE;
  167. }
  168. /*----------------------------------------------------------------------------*\
  169. | wsStartWait() |
  170. | |
  171. | Turn the WinSetup cursor to a hour glass |
  172. | |
  173. \*----------------------------------------------------------------------------*/
  174. void wsStartWait()
  175. {
  176. SetCursor(LoadCursor(NULL,IDC_WAIT));
  177. }
  178. /*----------------------------------------------------------------------------*\
  179. | wsEndWait() |
  180. | |
  181. | Turn the WinSetup cursor back to what it was |
  182. | |
  183. \*----------------------------------------------------------------------------*/
  184. void wsEndWait()
  185. {
  186. SetCursor(LoadCursor(NULL,IDC_ARROW));
  187. }
  188. /*----------------------------------------------------------------------------*\
  189. | fDialog(id,hwnd,fpfn) |
  190. | |
  191. | Description: |
  192. | This function displays a dialog box and returns the exit code. |
  193. | |
  194. | Arguments: |
  195. | id resource id of dialog to display |
  196. | hwnd parent window of dialog |
  197. | fpfn dialog message function |
  198. | |
  199. | Returns: |
  200. | exit code of dialog (what was passed to EndDialog) |
  201. | |
  202. \*----------------------------------------------------------------------------*/
  203. int fDialog(int id, HWND hwnd, DLGPROC fpfn)
  204. {
  205. return ( (int)DialogBox(myInstance, MAKEINTRESOURCE(id), hwnd, fpfn) );
  206. }
  207. /****************************************************************************
  208. * |
  209. *wsCopyError() |
  210. * |
  211. * Handles errors, as the result of copying files. |
  212. * |
  213. * This may include net contention errors, in which case the user must |
  214. * retry the operation. |
  215. * |
  216. * Parameters :
  217. *
  218. * n - Copy error number
  219. *
  220. * szFile - the fully qualified name of the file we are copying
  221. *
  222. * Returns
  223. *
  224. * Always returns FC_ABORT
  225. *
  226. ****************************************************************************/
  227. UINT wsCopyError(int n, LPSTR szFile)
  228. {
  229. char strBuf[MAXSTR];
  230. int i = 0;
  231. /*
  232. * We do not want to report any errors that occur while installing
  233. * related drivers to the user
  234. */
  235. if (bCopyingRelated)
  236. return(FC_ABORT);
  237. /*
  238. * check for out of disk space
  239. */
  240. if (n == ERROR_DISK_FULL) {
  241. LoadString(myInstance, IDS_OUTOFDISK, strBuf, MAXSTR);
  242. } else {
  243. /*
  244. * Check to see if a copy has been done on a file that is currently
  245. * loaded by the system.
  246. *
  247. * n is the return code from VerInstallFile after translating
  248. * by ConvertFlagToValue
  249. */
  250. if (n == FC_ERROR_LOADED_DRIVER)
  251. {
  252. int iIndex;
  253. BOOL bFound = FALSE;
  254. PIDRIVER pIDriver;
  255. iIndex = (int)SendMessage(hlistbox, LB_GETCOUNT, 0, 0L);
  256. /*
  257. * The driver is in use :
  258. *
  259. * Search the list of curently installed drivers to see
  260. * if this file is one of them. If so tell the user to
  261. * de-install and re-start.
  262. */
  263. while ( iIndex-- > 0 && !bFound) {
  264. if ( (int)(pIDriver = (PIDRIVER)SendMessage(hlistbox,
  265. LB_GETITEMDATA,
  266. iIndex,
  267. 0L)) != LB_ERR)
  268. {
  269. if (!lstrcmpi(pIDriver->szFile, FileName(szFile)))
  270. {
  271. char sztemp[MAXSTR];
  272. /*
  273. * Found the driver description.
  274. *
  275. * Tell the user to un-install it and restart
  276. * windows so that it's not loaded.
  277. */
  278. LoadString(myInstance,
  279. IDS_FILEINUSEREM,
  280. sztemp,
  281. sizeof(sztemp));
  282. wsprintf(strBuf, sztemp, (LPSTR)pIDriver->szDesc);
  283. bFound = TRUE;
  284. }
  285. }
  286. } // while ( iIndex-- > 0 && !bFound)
  287. /*
  288. * If the driver is not currently installed then tell
  289. * the user to re-start in the hope that it will then
  290. * not be loaded (and so in use)
  291. *
  292. * Note that there is another case not catered for that
  293. * this is just a file in the driver's copy list which
  294. * failed to copy because it was 'in use'.
  295. */
  296. if (!bFound)
  297. {
  298. iRestartMessage = IDS_FILEINUSEADD;
  299. DialogBox(myInstance,
  300. MAKEINTRESOURCE(DLG_RESTART),
  301. hMesgBoxParent,
  302. RestartDlg);
  303. return(FC_ABORT);
  304. }
  305. } else {
  306. /*
  307. * Tell the user there is a problem which we don't
  308. * understand here.
  309. */
  310. LoadString(myInstance,
  311. IDS_UNABLE_TOINSTALL,
  312. strBuf,
  313. MAXSTR);
  314. }
  315. }
  316. /*
  317. * Put up the message box we have selected.
  318. */
  319. MessageBox(hMesgBoxParent,
  320. strBuf,
  321. szFileError,
  322. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  323. return (FC_ABORT);
  324. }
  325. /*----------------------------------------------------------------------------*\
  326. | |
  327. | wsInsertDisk() |
  328. | |
  329. | Handles errors, as the result of copying files. |
  330. | |
  331. \*----------------------------------------------------------------------------*/
  332. UINT wsInsertDisk(LPSTR Disk, LPSTR szSrcPath)
  333. {
  334. UINT temp;
  335. int i;
  336. /*
  337. * Create the real disk letter
  338. */
  339. for (i = 0; Disk[i] != '\0' && Disk[i] != ':'; i++) {
  340. CurrentDisk[i] = Disk[i];
  341. }
  342. CurrentDisk[i] = '\0'; // Null terminate
  343. szEdit = szSrcPath;
  344. bFindOEM = TRUE;
  345. temp = (UINT)fDialog(DLG_INSERTDISK, GetActiveWindow(), wsDiskDlg);
  346. bFindOEM = FALSE;
  347. return(temp);
  348. }
  349. /*----------------------------------------------------------------------------*
  350. | wsDiskDlg( hDlg, uiMessage, wParam, lParam ) |
  351. | |
  352. | Arguments: |
  353. | hDlg window handle of about dialog window |
  354. | uiMessage message number |
  355. | wParam message-dependent |
  356. | lParam message-dependent |
  357. | |
  358. | Returns: |
  359. | TRUE if message has been processed, else FALSE |
  360. | |
  361. \*----------------------------------------------------------------------------*/
  362. BOOL wsDiskDlg(HWND hDlg, UINT uiMessage, UINT wParam, LPARAM lParam)
  363. {
  364. switch (uiMessage)
  365. {
  366. case WM_COMMAND:
  367. switch (LOWORD(wParam))
  368. {
  369. case IDH_DLG_INSERT_DISK:
  370. goto DoHelp;
  371. case IDS_BROWSE:
  372. /*
  373. * Call the browse dialog to open drivers
  374. */
  375. BrowseDlg(hDlg,
  376. 3); // index 3 points to no filter
  377. // - see szFilter
  378. break;
  379. case IDOK:
  380. /*
  381. * szEdit points to the path that will be retried
  382. * if the copy fails
  383. */
  384. GetDlgItemText(hDlg, ID_EDIT, szEdit, MAX_PATH);
  385. RemoveSpaces(szDiskPath, szEdit);
  386. lstrcpy(szEdit, szDiskPath);
  387. EndDialog(hDlg, FC_RETRY);
  388. UpdateWindow(hMesgBoxParent);
  389. break;
  390. case IDCANCEL:
  391. EndDialog(hDlg, FC_ABORT);
  392. break;
  393. }
  394. return TRUE;
  395. case WM_INITDIALOG:
  396. {
  397. char DisksSection[MAXSTR];
  398. /*
  399. * now look in the [disks] section for the disk name
  400. * the disk name is the second field.
  401. */
  402. char buf[MAXSTR];
  403. char buf2[MAXSTR];
  404. char bufout[MAXSTR];
  405. *buf = '\0';
  406. /*
  407. * See what the name of the section should be
  408. */
  409. LoadString(myInstance,
  410. IDS_DISKS,
  411. DisksSection,
  412. sizeof(DisksSection));
  413. infGetProfileString(NULL, DisksSection, CurrentDisk, (LPSTR)buf);
  414. if (*buf) {
  415. /*
  416. * Position of description in Windows NT
  417. */
  418. infParseField(buf, 1, buf2);
  419. } else {
  420. /*
  421. * Didn't find the section we were looking for so try
  422. * the old names
  423. */
  424. infGetProfileString(NULL, "disks", CurrentDisk, (LPSTR)buf);
  425. if (!*buf)
  426. infGetProfileString(NULL, "oemdisks", CurrentDisk, (LPSTR)buf);
  427. if (!*buf) {
  428. return FALSE;
  429. }
  430. infParseField(buf, 2, buf2);
  431. }
  432. wsprintf(bufout, szKnown, (LPSTR)buf2, (LPSTR)szDrv);
  433. SetDlgItemText(hDlg,ID_TEXT,bufout);
  434. SetDlgItemText(hDlg,ID_EDIT,szEdit);
  435. return TRUE;
  436. }
  437. default:
  438. if (uiMessage == wHelpMessage) {
  439. DoHelp:
  440. WinHelp(hDlg, szDriversHlp, HELP_CONTEXT, IDH_DLG_INSERT_DISK);
  441. return TRUE;
  442. }
  443. else
  444. return FALSE;
  445. break;
  446. }
  447. }
  448. /*--------------------------------------------------------------------------
  449. *
  450. * Function : wsCopySingleStatus
  451. * File copying callback routine
  452. *
  453. * Parameters :
  454. * msg - Which callback function
  455. * n - various
  456. * szFile - which file
  457. *
  458. * this call back only copies it's file if it does not exist in the
  459. * path.
  460. *
  461. *--------------------------------------------------------------------------*/
  462. UINT wsCopySingleStatus(int msg, DWORD n, LPSTR szFile)
  463. {
  464. OFSTRUCT ofs;
  465. char szFullPath[MAX_PATH];
  466. char szDriverExists[MAXSTR];
  467. switch (msg)
  468. {
  469. case COPY_INSERTDISK:
  470. return wsInsertDisk((LPSTR)n, szFile);
  471. case COPY_ERROR:
  472. return wsCopyError((int)n, szFile);
  473. case COPY_QUERYCOPY:
  474. /*
  475. * See if the file already exists in the windows system
  476. * directory
  477. */
  478. GetSystemDirectory(szFullPath, MAX_PATH);
  479. if (IsFileKernelDriver(szFile)) {
  480. lstrcat(szFullPath, "\\drivers");
  481. }
  482. lstrcat(szFullPath, "\\");
  483. lstrcat(szFullPath, RemoveDiskId(szFile));
  484. if (OpenFile(szFullPath, &ofs, OF_EXIST|OF_SHARE_DENY_NONE) >= 0)
  485. {
  486. /*
  487. * DriverCopy remembers whether to copy from
  488. * current or new after we have queried the user
  489. * once
  490. */
  491. static int DriverCopy;
  492. if (bQueryExist)
  493. {
  494. bQueryExist = FALSE;
  495. LoadString(myInstance,
  496. IDS_DRIVER_EXISTS,
  497. szDriverExists,
  498. sizeof(szDriverExists));
  499. wsprintf(szErrMsg, szDriverExists, FileName(szFile));
  500. /*
  501. * Ask the user whether to copy or not ?
  502. */
  503. DriverCopy = DialogBox(myInstance,
  504. MAKEINTRESOURCE(DLG_EXISTS),
  505. hMesgBoxParent,
  506. wsExistDlg);
  507. }
  508. return DriverCopy;
  509. } else {
  510. return CopyNew;
  511. }
  512. case COPY_START:
  513. case COPY_END:
  514. SetErrorMode(msg == COPY_START); // don't crit error on us
  515. break;
  516. }
  517. return FC_IGNORE;
  518. }
  519. /*
  520. * Function : wsExistDlg - 'File exists' dialog
  521. */
  522. BOOL wsExistDlg(HWND hDlg, UINT uiMessage, UINT wParam, LPARAM lParam)
  523. {
  524. switch (uiMessage)
  525. {
  526. case WM_COMMAND:
  527. switch (LOWORD(wParam))
  528. {
  529. case ID_CURRENT:
  530. EndDialog(hDlg, CopyCurrent);
  531. break;
  532. case ID_NEW:
  533. /*
  534. * User selected to copy the new files over the
  535. * existing ones
  536. */
  537. EndDialog(hDlg, CopyNew);
  538. break;
  539. case IDCANCEL:
  540. EndDialog(hDlg, CopyNeither); // Cancel
  541. break;
  542. }
  543. return TRUE;
  544. case WM_INITDIALOG:
  545. SetDlgItemText(hDlg, ID_STATUS2, szErrMsg);
  546. return TRUE;
  547. default:
  548. break;
  549. }
  550. return FALSE;
  551. }
  552. /*
  553. * Function : RemoveSpaces
  554. * Copies a string removing leading and trailing spaces but allowing
  555. * for long file names with internal spaces.
  556. *
  557. * Parameters :
  558. * szPath - The output result
  559. * szEdit - The input path
  560. */
  561. VOID RemoveSpaces(LPTSTR szPath, LPTSTR szEdit)
  562. {
  563. LPTSTR szLastSpaceList;
  564. while (*szEdit == ' ') {
  565. szEdit = CharNext(szEdit);
  566. }
  567. lstrcpy(szPath, szEdit);
  568. for (szLastSpaceList = NULL;
  569. *szPath != TEXT('\0');
  570. szPath = CharNext(szPath)) {
  571. if (*szPath == ' ') {
  572. if (szLastSpaceList == NULL) {
  573. szLastSpaceList = szPath;
  574. }
  575. } else {
  576. szLastSpaceList = NULL;
  577. }
  578. }
  579. if (szLastSpaceList != NULL) {
  580. *szLastSpaceList = TEXT('\0');
  581. }
  582. }