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.

720 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 TCHAR szErrMsg[MAXSTR];
  29. // Hidden parameters passed from wsInsertDisk to wDiskDlg
  30. static TCHAR CurrentDisk[MAX_PATH];
  31. static LPTSTR szEdit;
  32. // Function prototypes
  33. BOOL wsInfParseInit (void);
  34. int fDialog (int, HWND, DLGPROC);
  35. UINT wsCopyError (int, LPTSTR);
  36. UINT wsInsertDisk (LPTSTR, LPTSTR);
  37. INT_PTR wsDiskDlg (HWND, UINT, WPARAM, LPARAM);
  38. INT_PTR 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 LoadDescFromFile(PIDRIVER pIDriver, LPTSTR pstrKey, LPTSTR pstrDesc)
  50. {
  51. PINF pinf;
  52. TCHAR szFileName[MAX_INF_LINE_LEN];
  53. LPTSTR pstrFile = pIDriver->szFile;
  54. TCHAR ExpandedName[MAX_PATH];
  55. LPTSTR 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(LPTSTR 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. (LPBYTE)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. TCHAR szPathName[MAX_PATH];
  123. TCHAR* pszFilePart;
  124. PINF pinf;
  125. TCHAR szNoInf[MAXSTR];
  126. TCHAR iDrive;
  127. static BOOL bChkCDROM = FALSE;
  128. HANDLE hFile;
  129. szPathName[0] = '\0';
  130. /*
  131. * put up an hour glass here
  132. */
  133. wsStartWait();
  134. hFile = CreateFile(szSetupInf, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  135. if (hFile == INVALID_HANDLE_VALUE)
  136. {
  137. wsEndWait();
  138. LoadString(myInstance, IDS_NOINF, szNoInf, sizeof(szNoInf)/sizeof(TCHAR));
  139. MessageBox(hMesgBoxParent, szNoInf, szDrivers, MB_OK | MB_ICONEXCLAMATION);
  140. return FALSE;
  141. }
  142. CloseHandle(hFile);
  143. GetFullPathName(szSetupInf,sizeof(szPathName)/sizeof(TCHAR),szPathName,&pszFilePart);
  144. pinf = infOpen(szPathName);
  145. wsEndWait();
  146. if (GetWindowsDirectory(szSetupPath, sizeof(szSetupPath)/sizeof(TCHAR)))
  147. szSetupPath[0] = '\0';
  148. if (bChkCDROM == FALSE) {
  149. /*
  150. * Use the setup path from the registry if there is one
  151. */
  152. if (!GetInstallPath(szDirOfSrc))
  153. {
  154. /*
  155. * use the CD ROM drive as the default drive (if there is one)
  156. */
  157. for ( iDrive=TEXT('A'); iDrive <= TEXT('Z'); iDrive++ ) {
  158. szDirOfSrc[0] = iDrive;
  159. if ( GetDriveType(szDirOfSrc) == DRIVE_CDROM)
  160. {
  161. break;
  162. }
  163. /*
  164. * If we didn't find a CD ROM default to the A drive
  165. */
  166. if (iDrive == TEXT('Z')) {
  167. szDirOfSrc[0] = TEXT('A');
  168. }
  169. }
  170. }
  171. bChkCDROM = TRUE;
  172. }
  173. lstrcpy(szDiskPath, szDirOfSrc);
  174. return TRUE;
  175. }
  176. /*----------------------------------------------------------------------------*\
  177. | wsStartWait() |
  178. | |
  179. | Turn the WinSetup cursor to a hour glass |
  180. | |
  181. \*----------------------------------------------------------------------------*/
  182. void wsStartWait()
  183. {
  184. SetCursor(LoadCursor(NULL,IDC_WAIT));
  185. }
  186. /*----------------------------------------------------------------------------*\
  187. | wsEndWait() |
  188. | |
  189. | Turn the WinSetup cursor back to what it was |
  190. | |
  191. \*----------------------------------------------------------------------------*/
  192. void wsEndWait()
  193. {
  194. SetCursor(LoadCursor(NULL,IDC_ARROW));
  195. }
  196. /*----------------------------------------------------------------------------*\
  197. | fDialog(id,hwnd,fpfn) |
  198. | |
  199. | Description: |
  200. | This function displays a dialog box and returns the exit code. |
  201. | |
  202. | Arguments: |
  203. | id resource id of dialog to display |
  204. | hwnd parent window of dialog |
  205. | fpfn dialog message function |
  206. | |
  207. | Returns: |
  208. | exit code of dialog (what was passed to EndDialog) |
  209. | |
  210. \*----------------------------------------------------------------------------*/
  211. int fDialog(int id, HWND hwnd, DLGPROC fpfn)
  212. {
  213. return ( (int)DialogBox(myInstance, MAKEINTRESOURCE(id), hwnd, fpfn) );
  214. }
  215. /****************************************************************************
  216. * |
  217. *wsCopyError() |
  218. * |
  219. * Handles errors, as the result of copying files. |
  220. * |
  221. * This may include net contention errors, in which case the user must |
  222. * retry the operation. |
  223. * |
  224. * Parameters :
  225. *
  226. * n - Copy error number
  227. *
  228. * szFile - the fully qualified name of the file we are copying
  229. *
  230. * Returns
  231. *
  232. * Always returns FC_ABORT
  233. *
  234. ****************************************************************************/
  235. UINT wsCopyError(int n, LPTSTR szFile)
  236. {
  237. TCHAR strBuf[MAXSTR];
  238. int i = 0;
  239. /*
  240. * We do not want to report any errors that occur while installing
  241. * related drivers to the user
  242. */
  243. if (bCopyingRelated)
  244. return(FC_ABORT);
  245. /*
  246. * check for out of disk space
  247. */
  248. if (n == ERROR_DISK_FULL) {
  249. LoadString(myInstance, IDS_OUTOFDISK, strBuf, MAXSTR);
  250. } else {
  251. /*
  252. * Check to see if a copy has been done on a file that is currently
  253. * loaded by the system.
  254. *
  255. * n is the return code from VerInstallFile after translating
  256. * by ConvertFlagToValue
  257. */
  258. if (n == FC_ERROR_LOADED_DRIVER)
  259. {
  260. BOOL bFound = FALSE;
  261. PIDRIVER pIDriver;
  262. /*
  263. * The driver is in use :
  264. *
  265. * Search the list of curently installed drivers to see
  266. * if this file is one of them. If so tell the user to
  267. * de-install and re-start.
  268. *
  269. * If the driver is not currently installed then tell
  270. * the user to re-start in the hope that it will then
  271. * not be loaded (and so in use)
  272. *
  273. * Note that there is another case not catered for that
  274. * this is just a file in the driver's copy list which
  275. * failed to copy because it was 'in use'.
  276. *
  277. */
  278. pIDriver = FindIDriverByName (FileName(szFile));
  279. if (pIDriver != NULL) // Found an already-installed driver?
  280. {
  281. TCHAR sztemp[MAXSTR];
  282. LoadString(myInstance,
  283. IDS_FILEINUSEREM,
  284. sztemp,
  285. sizeof(sztemp)/sizeof(TCHAR));
  286. wsprintf(strBuf, sztemp, (LPTSTR)pIDriver->szDesc);
  287. bFound = TRUE;
  288. } else {
  289. iRestartMessage = IDS_FILEINUSEADD;
  290. DialogBox(myInstance,
  291. MAKEINTRESOURCE(DLG_RESTART),
  292. hMesgBoxParent,
  293. RestartDlg);
  294. return(FC_ABORT);
  295. }
  296. } else {
  297. /*
  298. * Tell the user there is a problem which we don't
  299. * understand here.
  300. */
  301. LoadString(myInstance,
  302. IDS_UNABLE_TOINSTALL,
  303. strBuf,
  304. MAXSTR);
  305. }
  306. }
  307. /*
  308. * Put up the message box we have selected.
  309. */
  310. MessageBox(hMesgBoxParent,
  311. strBuf,
  312. szFileError,
  313. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  314. return (FC_ABORT);
  315. }
  316. /*----------------------------------------------------------------------------*\
  317. | |
  318. | wsInsertDisk() |
  319. | |
  320. | Handles errors, as the result of copying files. |
  321. | |
  322. \*----------------------------------------------------------------------------*/
  323. UINT wsInsertDisk(LPTSTR Disk, LPTSTR szSrcPath)
  324. {
  325. UINT temp;
  326. int i;
  327. /*
  328. * Create the real disk letter
  329. */
  330. for (i = 0; Disk[i] != TEXT('\0') && Disk[i] != TEXT(':'); i++) {
  331. CurrentDisk[i] = Disk[i];
  332. }
  333. CurrentDisk[i] = TEXT('\0'); // Null terminate
  334. szEdit = szSrcPath;
  335. bFindOEM = TRUE;
  336. temp = (UINT)fDialog(DLG_INSERTDISK, GetActiveWindow(), wsDiskDlg);
  337. bFindOEM = FALSE;
  338. return(temp);
  339. }
  340. /*----------------------------------------------------------------------------*
  341. | wsDiskDlg( hDlg, uiMessage, wParam, lParam ) |
  342. | |
  343. | Arguments: |
  344. | hDlg window handle of about dialog window |
  345. | uiMessage message number |
  346. | wParam message-dependent |
  347. | lParam message-dependent |
  348. | |
  349. | Returns: |
  350. | TRUE if message has been processed, else FALSE |
  351. | |
  352. \*----------------------------------------------------------------------------*/
  353. INT_PTR wsDiskDlg(HWND hDlg, UINT uiMessage, WPARAM wParam, LPARAM lParam)
  354. {
  355. switch (uiMessage)
  356. {
  357. case WM_COMMAND:
  358. switch (LOWORD(wParam))
  359. {
  360. case IDH_DLG_INSERT_DISK:
  361. goto DoHelp;
  362. case IDS_BROWSE:
  363. /*
  364. * Call the browse dialog to open drivers
  365. */
  366. BrowseDlg(hDlg,
  367. 3); // index 3 points to no filter
  368. // - see szFilter
  369. break;
  370. case IDOK:
  371. /*
  372. * szEdit points to the path that will be retried
  373. * if the copy fails
  374. */
  375. GetDlgItemText(hDlg, ID_EDIT, szEdit, MAX_PATH);
  376. RemoveSpaces(szDiskPath, szEdit);
  377. lstrcpy(szEdit, szDiskPath);
  378. EndDialog(hDlg, FC_RETRY);
  379. UpdateWindow(hMesgBoxParent);
  380. break;
  381. case IDCANCEL:
  382. EndDialog(hDlg, FC_ABORT);
  383. break;
  384. }
  385. return TRUE;
  386. case WM_INITDIALOG:
  387. {
  388. TCHAR DisksSection[MAXSTR];
  389. /*
  390. * now look in the [disks] section for the disk name
  391. * the disk name is the second field.
  392. */
  393. TCHAR buf[MAXSTR];
  394. TCHAR buf2[MAXSTR];
  395. TCHAR bufout[MAXSTR];
  396. *buf = TEXT('\0');
  397. /*
  398. * See what the name of the section should be
  399. */
  400. LoadString(myInstance,
  401. IDS_DISKS,
  402. DisksSection,
  403. sizeof(DisksSection)/sizeof(TCHAR));
  404. infGetProfileString(NULL, DisksSection, CurrentDisk, (LPTSTR)buf);
  405. if (*buf) {
  406. /*
  407. * Position of description in Windows NT
  408. */
  409. infParseField(buf, 1, buf2);
  410. } else {
  411. /*
  412. * Didn't find the section we were looking for so try
  413. * the old names
  414. */
  415. infGetProfileString(NULL, TEXT("disks"), CurrentDisk, (LPTSTR)buf);
  416. if (!*buf)
  417. infGetProfileString(NULL, TEXT("oemdisks"), CurrentDisk, (LPTSTR)buf);
  418. if (!*buf) {
  419. return FALSE;
  420. }
  421. infParseField(buf, 2, buf2);
  422. }
  423. wsprintf(bufout, szKnown, (LPTSTR)buf2, (LPTSTR)szDrv);
  424. SetDlgItemText(hDlg,ID_TEXT,bufout);
  425. SetDlgItemText(hDlg,ID_EDIT,szEdit);
  426. return TRUE;
  427. }
  428. default:
  429. if (uiMessage == wHelpMessage) {
  430. DoHelp:
  431. WinHelp(hDlg, szDriversHlp, HELP_CONTEXT, IDH_DLG_INSERT_DISK);
  432. return TRUE;
  433. }
  434. else
  435. return FALSE;
  436. break;
  437. }
  438. }
  439. /*--------------------------------------------------------------------------
  440. *
  441. * Function : wsCopySingleStatus
  442. * File copying callback routine
  443. *
  444. * Parameters :
  445. * msg - Which callback function
  446. * n - various
  447. * szFile - which file
  448. *
  449. * this call back only copies it's file if it does not exist in the
  450. * path.
  451. *
  452. *--------------------------------------------------------------------------*/
  453. UINT wsCopySingleStatus(int msg, DWORD_PTR n, LPTSTR szFile)
  454. {
  455. OFSTRUCT ofs;
  456. TCHAR szFullPath[MAX_PATH];
  457. TCHAR szDriverExists[MAXSTR];
  458. switch (msg)
  459. {
  460. case COPY_INSERTDISK:
  461. return wsInsertDisk((LPTSTR)n, szFile);
  462. case COPY_ERROR:
  463. return wsCopyError((int)n, szFile);
  464. case COPY_QUERYCOPY:
  465. /*
  466. * See if the file already exists in the windows system
  467. * directory
  468. */
  469. GetSystemDirectory(szFullPath, MAX_PATH);
  470. if (IsFileKernelDriver(szFile)) {
  471. lstrcat(szFullPath, TEXT("\\drivers"));
  472. }
  473. lstrcat(szFullPath, TEXT("\\"));
  474. lstrcat(szFullPath, RemoveDiskId(szFile));
  475. // BUGBUG -- handle leak since time immemorial
  476. if (CreateFile(szFullPath, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) != INVALID_HANDLE_VALUE)
  477. {
  478. /*
  479. * DriverCopy remembers whether to copy from
  480. * current or new after we have queried the user
  481. * once
  482. */
  483. static int DriverCopy;
  484. if (bQueryExist)
  485. {
  486. bQueryExist = FALSE;
  487. LoadString(myInstance,
  488. IDS_DRIVER_EXISTS,
  489. szDriverExists,
  490. sizeof(szDriverExists)/sizeof(TCHAR));
  491. wsprintf(szErrMsg, szDriverExists, FileName(szFile));
  492. /*
  493. * Ask the user whether to copy or not ?
  494. */
  495. DriverCopy = (int)DialogBox(myInstance,
  496. MAKEINTRESOURCE(DLG_EXISTS),
  497. hMesgBoxParent,
  498. wsExistDlg);
  499. }
  500. return DriverCopy;
  501. } else {
  502. return CopyNew;
  503. }
  504. case COPY_START:
  505. case COPY_END:
  506. SetErrorMode(msg == COPY_START); // don't crit error on us
  507. break;
  508. }
  509. return FC_IGNORE;
  510. }
  511. /*
  512. * Function : wsExistDlg - 'File exists' dialog
  513. */
  514. INT_PTR wsExistDlg(HWND hDlg, UINT uiMessage, WPARAM wParam, LPARAM lParam)
  515. {
  516. switch (uiMessage)
  517. {
  518. case WM_COMMAND:
  519. switch (LOWORD(wParam))
  520. {
  521. case ID_CURRENT:
  522. EndDialog(hDlg, CopyCurrent);
  523. break;
  524. case ID_NEW:
  525. /*
  526. * User selected to copy the new files over the
  527. * existing ones
  528. */
  529. EndDialog(hDlg, CopyNew);
  530. break;
  531. case IDCANCEL:
  532. EndDialog(hDlg, CopyNeither); // Cancel
  533. break;
  534. }
  535. return TRUE;
  536. case WM_INITDIALOG:
  537. SetDlgItemText(hDlg, ID_STATUS2, szErrMsg);
  538. return TRUE;
  539. default:
  540. break;
  541. }
  542. return FALSE;
  543. }
  544. /*
  545. * Function : RemoveSpaces
  546. * Copies a string removing leading and trailing spaces but allowing
  547. * for long file names with internal spaces.
  548. *
  549. * Parameters :
  550. * szPath - The output result
  551. * szEdit - The input path
  552. */
  553. VOID RemoveSpaces(LPTSTR szPath, LPTSTR szEdit)
  554. {
  555. LPTSTR szLastSpaceList;
  556. while (*szEdit == TEXT(' ')) {
  557. szEdit = CharNext(szEdit);
  558. }
  559. lstrcpy(szPath, szEdit);
  560. for (szLastSpaceList = NULL;
  561. *szPath != TEXT('\0');
  562. szPath = CharNext(szPath)) {
  563. if (*szPath == TEXT(' ')) {
  564. if (szLastSpaceList == NULL) {
  565. szLastSpaceList = szPath;
  566. }
  567. } else {
  568. szLastSpaceList = NULL;
  569. }
  570. }
  571. if (szLastSpaceList != NULL) {
  572. *szLastSpaceList = TEXT('\0');
  573. }
  574. }