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.

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