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.

932 lines
25 KiB

  1. /*
  2. * copy.c - Copy routine for WinDosSetup
  3. * Todd Laney
  4. *
  5. * Modification History:
  6. *
  7. * 6/03/91 Vlads Change copy process to incorporate new Install API
  8. *
  9. * 3/24/89 Toddla Wrote it
  10. *
  11. *
  12. * notes:
  13. * we now use the LZCopy stuff for compression
  14. * we now set the crit error handler ourselves so CHECKFLOPPY is
  15. * NOT defined
  16. */
  17. #include <windows.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <mmsystem.h>
  22. #include "drivers.h"
  23. #include "sulib.h"
  24. //#include <ver.h>
  25. #define MAX_COPY_ATTEMPTS 15
  26. /*
  27. * Maximum number of install disks we support
  28. */
  29. #define MAX_DISKS 100
  30. /*
  31. * Flags for VerInstallFile
  32. */
  33. #define FORCEABLE_FLAGS (VIF_MISMATCH + VIF_SRCOLD + VIF_DIFFLANG + VIF_DIFFTYPE + VIF_DIFFCODEPG )
  34. /**********************************************************************
  35. *
  36. * Local function prototypes.
  37. *
  38. **********************************************************************/
  39. // Retrieve disk path for logical disk
  40. LONG GetDiskPath(LPTSTR Disk, LPTSTR szPath, size_t cchPath);
  41. // Convert VIF_... to ERROR... return codes
  42. UINT ConvertFlagToValue(DWORD dwFlags);
  43. // Do the work of trying to copy a file
  44. LONG TryCopy(LPTSTR szSrc, // Full source file path
  45. LPTSTR szLogSrc, // Logical source name
  46. LPTSTR szDestPath,// Destination path
  47. FPFNCOPY fpfnCopy); // Callback routine
  48. #ifdef CHECK_FLOPPY
  49. BOOL NEAR IsDiskInDrive(int iDisk);
  50. #endif
  51. // GLOBAL VARIABLES
  52. // directory where windows will be setup to
  53. TCHAR szSetupPath[MAX_PATH];
  54. // directory where the root of the setup disks are!
  55. TCHAR szDiskPath[MAX_PATH];
  56. // Name of driver being copied (or oemsetup.inf)
  57. TCHAR szDrv[120];
  58. /*
  59. * global vars used by DosCopy
  60. */
  61. static LPTSTR lpBuf = NULL; // copy buffer
  62. static int iBuf = 0; // usage count
  63. static UINT nBufSize;
  64. BOOL bRetry = FALSE;
  65. BOOL bQueryExist;
  66. extern BOOL bCopyEvenIfOlder; // From DRIVERS.C
  67. BOOL DefCopyCallback(int msg, DWORD_PTR n, LPTSTR szFile)
  68. {
  69. return FC_IGNORE;
  70. }
  71. /* UINT FileCopy (szSource, szDir, fpfnCopy, UINT fCopy)
  72. *
  73. * This function will copy a group of files to a single destination
  74. *
  75. * ENTRY:
  76. *
  77. * szSourc : pointer to a SETUP.INF section
  78. * szDir : pointer to a string containing the target DIR
  79. * fpfnCopy : callback function used to notify called of copy status
  80. * fCopy : flags
  81. *
  82. * FC_SECTION - szSource is a section name
  83. * FC_LIST - szSource is a pointer to a char **foo;
  84. * FC_LISTTYPE - szSource is a pointer to a char *foo[];
  85. * FC_FILE - szSource is a file name.
  86. * FC_QUALIFIED - szSource is a fully qualified file name.
  87. * FC_DEST_QUALIFIED - szDir is fully qualified. Don't expand this.
  88. * FC_CALLBACK_WITH_VER - call back if file exists and report version information.
  89. *
  90. * NOTES:
  91. * if szSource points to a string of the form '#name' the section
  92. * named by 'name' will be used as the source files
  93. *
  94. * the first field of each line in the secion is used as the name of the
  95. * source file. A file name has the following form:
  96. *
  97. * #:name
  98. *
  99. * # - Disk number containing file 1-9,A-Z
  100. * name - name of the file, may be a wild card expression
  101. *
  102. * Format for copy status function
  103. *
  104. * BOOL FAR PASCAL CopyStatus(int msg, int n, LPSTR szFile)
  105. *
  106. * msg:
  107. * COPY_ERROR error occured while copying file(s)
  108. * n is the DOS error number
  109. * szFile is the file that got the error
  110. * return: TRUE ok, FALSE abort copy
  111. *
  112. * COPY_STATUS Called each time a new file is copied
  113. * n is the percent done
  114. * szFile is the file being copied
  115. * return: TRUE ok, FALSE abort copy
  116. *
  117. * COPY_INSERTDISK Please tell the user to insert a disk
  118. * n is the disk needed ('1' - '9')
  119. * return: TRUE try again, FALSE abort copy
  120. *
  121. * COPY_QUERYCOPY Should this file be copied?
  122. * n line index in SETUP.INF section (0 based)
  123. * szFile is the line from section
  124. * return: TRUE copy it, FALSE dont copy
  125. *
  126. * COPY_START Sent before any files are copied
  127. *
  128. * COPY_END Sent after all files have been copied
  129. * n is dos error if copy failed
  130. *
  131. * COPY_EXISTS Sent if the FC_CALL_ON_EXIST bit was set
  132. * and the file exists at the destination
  133. * given for the filecopy.
  134. *
  135. *
  136. * EXIT: returns TRUE if successful, FALSE if failure.
  137. *
  138. */
  139. UINT FileCopy (LPTSTR szSource, LPTSTR szDir, FPFNCOPY fpfnCopy, UINT fCopy)
  140. {
  141. int err = ERROR_SUCCESS; // Return code from this routine
  142. TCHAR szPath[MAX_PATH];
  143. TCHAR szLogSrc[MAX_PATH];
  144. TCHAR szSrc[MAX_PATH];
  145. LPTSTR pFileBegin; // First file
  146. LPTSTR * List; // Handle lists of files
  147. LPTSTR * ListHead;
  148. int nDisk; // The disk we're on
  149. int cntFiles = 0; // How many files we've got to do
  150. if (fpfnCopy == NULL) {
  151. fpfnCopy = DefCopyCallback;
  152. }
  153. if (!szSource || !*szSource || !szDir || !*szDir) {
  154. return ERROR_FILE_NOT_FOUND;
  155. }
  156. /*
  157. * fix up the drive in the destination
  158. */
  159. if ( fCopy & FC_DEST_QUALIFIED ) {
  160. lstrcpy(szPath, szDir);
  161. fCopy &= ~FC_DEST_QUALIFIED;
  162. } else {
  163. err = ExpandFileName(szDir, szPath);
  164. if (err != ERROR_SUCCESS)
  165. {
  166. (*fpfnCopy)(COPY_ERROR, err, szDir);
  167. return err;
  168. }
  169. }
  170. if (szSource[0] == TEXT('#') && fCopy == FC_FILE) {
  171. fCopy = FC_SECTION;
  172. ++szSource;
  173. }
  174. switch (fCopy) {
  175. case FC_SECTION:
  176. {
  177. szSource = infFindSection(NULL,szSource);
  178. /*
  179. * We are called even when the section doesn't exist
  180. */
  181. if (szSource == NULL) {
  182. return ERROR_SUCCESS;
  183. }
  184. fCopy = FC_LIST;
  185. }
  186. // fall through to FC_LIST
  187. case FC_LIST:
  188. pFileBegin = szSource;
  189. cntFiles = infLineCount(szSource);
  190. break;
  191. case FC_LISTTYPE:
  192. ListHead = List = (LPTSTR far *)szSource;
  193. pFileBegin = *ListHead;
  194. while ( *List++ ) // Count files to be copied.
  195. ++cntFiles;
  196. break;
  197. case FC_FILE:
  198. case FC_QUALIFIED:
  199. default:
  200. pFileBegin = szSource;
  201. cntFiles = 1;
  202. }
  203. /*
  204. * walk all files in the list and call TryCopy ....
  205. *
  206. * NOTES:
  207. * we must walk file list sorted by disk number.
  208. * we should use the disk that is currently inserted.
  209. * we should do a find first/find next on the files????
  210. * we need to check for errors.
  211. * we need to ask the user to insert disk in drive.
  212. *
  213. */
  214. (*fpfnCopy)(COPY_START,0,NULL);
  215. /*
  216. * Go through all possible disks: 1 to 100 and A to Z (26)
  217. */
  218. for (nDisk = 1;
  219. err == ERROR_SUCCESS && (cntFiles > 0) &&
  220. (nDisk <= MAX_DISKS + 'Z' - 'A' + 1);
  221. nDisk++)
  222. {
  223. TCHAR Disk[10]; // Maximum string is "100:"
  224. LPTSTR pFile;
  225. int FileNumber; // Which file in the list we're on
  226. // (to pass to callback)
  227. pFile = pFileBegin; // Start at first file
  228. List = ListHead; // Handled chained lists
  229. FileNumber = 0; // Informational for callback - gives
  230. // which file in list we're on
  231. /*
  232. * Work out the string representing our disk letter
  233. */
  234. if (nDisk > MAX_DISKS) {
  235. Disk[0] = TEXT('A') + nDisk - MAX_DISKS - 1;
  236. Disk[1] = TEXT('\0');
  237. } else {
  238. _itow(nDisk, Disk, 10);
  239. }
  240. wcscat(Disk, TEXT(":"));
  241. for (;
  242. err == ERROR_SUCCESS && pFile;
  243. FileNumber++,
  244. pFile = fCopy == FC_LISTTYPE ? *(++List) :
  245. fCopy == FC_LIST ? infNextLine(pFile) :
  246. NULL)
  247. {
  248. /*
  249. * We have to reset high bit of first byte because it could be set
  250. * by translating service in OEM setup to show that file name was
  251. * mapped
  252. */
  253. *pFile = toascii(*pFile);
  254. /*
  255. * should we copy this file?
  256. * copy the files in disk order.
  257. */
  258. if (_wcsnicmp(pFile, Disk, wcslen(Disk)) == 0 || // File has disk
  259. // number and we're
  260. // on that disk
  261. RemoveDiskId(pFile) == pFile &&
  262. nDisk == 1 && *pFile || // First disk and
  263. // no disk number
  264. fCopy == FC_QUALIFIED) { // Fully qualified
  265. /*
  266. * done with a file. decrement count.
  267. */
  268. cntFiles--;
  269. lstrcpy(szDrv, RemoveDiskId(pFile));
  270. switch ((*fpfnCopy)(COPY_QUERYCOPY, FileNumber, pFile))
  271. {
  272. case CopyCurrent: // Skip
  273. continue;
  274. case CopyNeither:
  275. err = ERROR_FILE_EXISTS; // File already exists
  276. case CopyNew:
  277. break;
  278. default:
  279. break;
  280. }
  281. /*
  282. * Pick up bad return code from switch
  283. */
  284. if (err != ERROR_SUCCESS) {
  285. break;
  286. }
  287. /*
  288. * now we convert logical dest into a physical
  289. * (unless FC_QUALIFIED)
  290. */
  291. err = infParseField(pFile, 1, szLogSrc, SIZEOF(szLogSrc)); // logical source
  292. if( INF_PARSE_FAILED(err) ) {
  293. (*fpfnCopy)(COPY_ERROR, err, pFile);
  294. break;
  295. }
  296. if ( fCopy != FC_QUALIFIED )
  297. {
  298. err = ExpandFileName(szLogSrc, szSrc); // full physical source
  299. if (err != ERROR_SUCCESS) {
  300. (*fpfnCopy)(COPY_ERROR, err, szLogSrc);
  301. break;
  302. }
  303. } else {
  304. lstrcpy(szSrc,szLogSrc);
  305. }
  306. /*
  307. * Attempt copy
  308. */
  309. err = TryCopy(szSrc, // Qualified Source file
  310. szLogSrc, // Logical source file name (with disk #)
  311. szPath, // Path for directory to install in
  312. fpfnCopy); // Copy callback function
  313. /*
  314. * If failed to find file try the windows directory
  315. */
  316. if (err != ERROR_SUCCESS) {
  317. break;
  318. }
  319. } /* End if dor if DoCopy */
  320. }
  321. }
  322. (*fpfnCopy)(COPY_END,err,NULL);
  323. return err;
  324. }
  325. /**********************************************************************
  326. *
  327. * TryCopy
  328. *
  329. * Copy a single file from source to destination using the VerInstallFile
  330. * API - interpreting the return code as :
  331. *
  332. * ERROR_SUCCESS - OK
  333. * Other - failure type
  334. *
  335. **********************************************************************/
  336. LONG TryCopy(LPTSTR szSrc, // Full expanded source file path
  337. LPTSTR szLogSrc, // Logical source name
  338. LPTSTR szDestPath, // Destination path
  339. FPFNCOPY fpfnCopy) // Callback routine
  340. {
  341. DWORD wTmpLen;
  342. DWORD dwRetFlags;
  343. TCHAR szTempFile[MAX_PATH];
  344. TCHAR szErrFile[MAX_PATH];
  345. TCHAR DriversPath[MAX_PATH];
  346. BOOL bRetVal; // Return code from callback
  347. LPTSTR szFile;
  348. TCHAR szSrcPath[MAX_PATH];
  349. int iAttemptCount;
  350. WORD wVerFlags;
  351. LONG err;
  352. LONG lResult;
  353. /*
  354. * Fix up destination if file is a kernel driver
  355. */
  356. if (IsFileKernelDriver(szSrc) && szDestPath)
  357. {
  358. wcscpy(DriversPath, szDestPath);
  359. wcscat(DriversPath, TEXT("\\drivers"));
  360. szDestPath = DriversPath;
  361. }
  362. /*
  363. * Create file name from current string
  364. */
  365. szFile = FileName(szSrc);
  366. lstrcpy(szSrcPath, szSrc);
  367. StripPathName(szSrcPath);
  368. for(iAttemptCount = 0, wVerFlags = 0 ;
  369. iAttemptCount <= MAX_COPY_ATTEMPTS;
  370. iAttemptCount++) {
  371. HCURSOR hcurPrev; // Saved cursor state
  372. // Central operation - attempt to install file szFile in directory
  373. // pointed by szPath from directory pointed by szSrc
  374. // If operation will fail but with possibility to force install
  375. // in last parameter buffer we will have temporary file name ==>
  376. // therefore we can avoid excessive copying.
  377. // NOTE: now szFile consists of only file name and other buffers
  378. // only path names.
  379. wTmpLen = MAX_PATH;
  380. hcurPrev = SetCursor(LoadCursor(NULL,IDC_WAIT));
  381. dwRetFlags = VerInstallFile(wVerFlags,
  382. (LPTSTR) szFile,
  383. (LPTSTR) szFile,
  384. (LPTSTR) szSrcPath,
  385. (LPTSTR) szDestPath,
  386. (LPTSTR) szDestPath,
  387. (LPTSTR) szTempFile,
  388. (LPDWORD) &wTmpLen);
  389. SetCursor(hcurPrev);
  390. /*
  391. * Operation failed if at least one bit of return flags is non-zero
  392. * That is unusual but defined so in Version API.
  393. */
  394. if ( !dwRetFlags )
  395. return ERROR_SUCCESS; // If no errors - goto next file
  396. /*
  397. * If flag MISMATCH is set - install can be forced and we have
  398. * temporary file in destination subdirectory
  399. */
  400. if ( dwRetFlags & VIF_MISMATCH ) {
  401. if ( (dwRetFlags & VIF_SRCOLD) && (!bCopyEvenIfOlder) ) {
  402. /*
  403. * If we need not call back with question - automatically
  404. * force install with same parameters.
  405. * michaele, *only* if src file is *newer* than dst file
  406. */
  407. DeleteFile(szTempFile);
  408. return ERROR_SUCCESS;
  409. }
  410. /*
  411. * If we need not call back with question - automatically
  412. * force install with same parameters.
  413. */
  414. wVerFlags |= VIFF_FORCEINSTALL;
  415. iAttemptCount--; // Make sure we get another go.
  416. continue;
  417. } /* End if MISMATCH */
  418. /*
  419. * If real error occured - call back with error file info
  420. * In all dialogs we use our error codes - so I will convert
  421. * flags returned from Ver API to ours.
  422. */
  423. err = ConvertFlagToValue(dwRetFlags);
  424. /*
  425. * If source path or file is nor readable - try to change disk
  426. */
  427. if ( dwRetFlags & VIF_CANNOTREADSRC )
  428. {
  429. /*
  430. * Now new path in szSrc so I deleted logic for creating it
  431. */
  432. if (RemoveDiskId(szLogSrc) == szLogSrc)
  433. /*
  434. * if disk # not provided, default to 1
  435. */
  436. bRetVal = (*fpfnCopy)(COPY_INSERTDISK, (DWORD_PTR)"1", szSrcPath);
  437. else
  438. bRetVal = (*fpfnCopy)(COPY_INSERTDISK, (DWORD_PTR)szLogSrc, szSrcPath);
  439. switch (bRetVal)
  440. {
  441. case FC_RETRY:
  442. continue; // and try again...
  443. case FC_ABORT:
  444. return ERROR_FILE_NOT_FOUND;
  445. case FC_IGNORE:
  446. break;
  447. }
  448. }
  449. lResult = ExpandFileName(szLogSrc, szErrFile);
  450. if (lResult != ERROR_SUCCESS)
  451. {
  452. (*fpfnCopy)(COPY_ERROR, lResult, szLogSrc);
  453. return lResult;
  454. }
  455. #if WINDOWSDIR
  456. if (!*bWindowsDir &&
  457. err != FC_ERROR_LOADED_DRIVER &&
  458. err != ERROR_DISK_FULL)
  459. {
  460. GetWindowsDirectory(szPath, MAX_PATH);
  461. *bWindowsDir = TRUE;
  462. continue;
  463. }
  464. #endif // WINDOWSDIR
  465. switch ((*fpfnCopy)(COPY_ERROR, err, szErrFile)) {
  466. case FC_IGNORE:
  467. return ERROR_SUCCESS;
  468. case FC_RETRY:
  469. break;
  470. case FC_ABORT:
  471. return ERROR_FILE_NOT_FOUND;
  472. }
  473. } // End of attempts
  474. return err;
  475. }
  476. /* LONG GetDiskPath(Disk, szPath, cchPath)
  477. *
  478. * This function will retrive the full path name for a logical disk
  479. *
  480. * The code reads the [disks] section of SETUP.INF and looks for
  481. * n = path where n is the disk char. NOTE the disk '0' defaults to
  482. * the root windows directory.
  483. *
  484. * ENTRY:
  485. *
  486. * cDisk : what disk to find 0-9,A-Z
  487. * szPath : buffer to hold disk path
  488. * cchPath : size of destination buffer (szPath) in characters.
  489. * length must be large enough to hold all of the
  490. * text including the null terminator.
  491. *
  492. * Returns :
  493. * ERROR_SUCCESS if a disk path was found
  494. * ERROR_INSUFFICIENT_BUFFER if szPath is too small to hold disk path
  495. * ERROR_NOT_FOUND if there was no disk specified (ie no ':'
  496. *
  497. */
  498. LONG GetDiskPath(LPTSTR Disk, LPTSTR szPath, size_t cchPath)
  499. {
  500. TCHAR ach[MAX_PATH];
  501. TCHAR szBuf[MAX_PATH];
  502. LONG lResult;
  503. int i;
  504. /*
  505. * Check to see if there is actually a disk id.
  506. * If not return ERROR_NOT_FOUND
  507. */
  508. if (RemoveDiskId(Disk) == Disk) {
  509. return ERROR_NOT_FOUND;
  510. }
  511. /*
  512. * Create our copy of the disk id
  513. */
  514. for (i = 0; Disk[i] != TEXT(':'); i++) {
  515. ach[i] = Disk[i];
  516. }
  517. ach[i] = TEXT('\0');
  518. /*
  519. * Zero disk letter means windows setup directory
  520. */
  521. if (_wcsicmp(ach, TEXT("0")) == 0) {
  522. /*
  523. * return the windows setup directory
  524. */
  525. lstrcpy(szPath,szSetupPath);
  526. return ERROR_SUCCESS;
  527. }
  528. /*
  529. * now look in the [disks] section for a full path name
  530. *
  531. * This is a pretty bogus concept and is not supported
  532. * in win 32 style disks section [Source Media Descriptions]
  533. */
  534. lResult = infGetProfileString(NULL,DISK_SECT,ach,szPath,cchPath);
  535. if (ERROR_NOT_FOUND == lResult)
  536. {
  537. lResult = infGetProfileString(NULL,OEMDISK_SECT,ach,szPath,cchPath);
  538. }
  539. if (ERROR_SUCCESS == lResult)
  540. {
  541. lResult = infParseField(szPath,1,szPath,cchPath);
  542. if( INF_PARSE_SUCCESS(lResult) )
  543. {
  544. /*
  545. * is the path relative? is so prepend the szDiskPath
  546. */
  547. if (szPath[0] == TEXT('.') || szPath[0] == TEXT('\0')) {
  548. lstrcpy(szBuf,szDiskPath);
  549. catpath(szBuf,szPath);
  550. lstrcpy(szPath,szBuf);
  551. }
  552. lResult = ERROR_SUCCESS;
  553. }
  554. }
  555. else if (ERROR_NOT_FOUND == lResult)
  556. {
  557. lstrcpy(szPath, szDiskPath);
  558. lResult = ERROR_SUCCESS;
  559. }
  560. return lResult;
  561. }
  562. /* LONG FAR PASCAL ExpandFileName(LPSTR szFile, LPTSTR szPath)
  563. *
  564. * This function will retrive the full path name for a file
  565. * it will expand, logical disk letters to pyshical ones
  566. * will use current disk and directory if non specifed.
  567. *
  568. * if the drive specifed is 0-9, it will expand the drive into a
  569. * full pathname using GetDiskPath()
  570. *
  571. * IE 0:system ==> c:windows\system
  572. * 1:foo.txt a:\foo.txt
  573. *
  574. * ENTRY:
  575. *
  576. * szFile : File name to expand
  577. * szPath : buffer to hold full file name
  578. *
  579. */
  580. LONG ExpandFileName(LPTSTR szFile, LPTSTR szPath)
  581. {
  582. TCHAR szBuf[MAX_PATH*2];
  583. LONG lResult;
  584. lResult = GetDiskPath(szFile, szBuf, SIZEOF(szBuf));
  585. if (ERROR_SUCCESS == lResult)
  586. {
  587. lstrcpy(szPath,szBuf);
  588. if (szFile[2])
  589. catpath(szPath,szFile + 2);
  590. }
  591. else if (ERROR_NOT_FOUND == lResult)
  592. {
  593. lstrcpy(szPath,szFile);
  594. lResult = ERROR_SUCCESS;
  595. }
  596. else
  597. {
  598. szPath[0] = 0;
  599. }
  600. return lResult;
  601. }
  602. void catpath(LPTSTR path, LPTSTR sz)
  603. {
  604. //
  605. // Remove any drive letters from the directory to append
  606. //
  607. sz = RemoveDiskId(sz);
  608. //
  609. // Remove any current directories ".\" from directory to append
  610. //
  611. while (sz[0] == TEXT('.') && SLASH(sz[1]))
  612. sz += 2;
  613. //
  614. // Dont append a NULL string or a single "."
  615. //
  616. if (*sz && ! (sz[0] == TEXT('.') && sz[1] == 0))
  617. {
  618. // Add a slash separator if necessary.
  619. if ((! SLASH(path[lstrlen(path) - 1])) && // slash at end of path
  620. ((path[lstrlen(path) - 1]) != TEXT(':')) && // colon at end of path
  621. (! SLASH(sz[0]))) // slash at beginning of file
  622. lstrcat(path, CHSEPSTR);
  623. lstrcat(path, sz);
  624. }
  625. }
  626. /*
  627. * Return a pointer to the file name part of a string
  628. */
  629. LPTSTR FileName(LPTSTR szPath)
  630. {
  631. LPTSTR sz;
  632. for (sz=szPath; *sz; sz++)
  633. ;
  634. for (; sz>=szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz--)
  635. ;
  636. return ++sz;
  637. }
  638. /*
  639. * Return the portion of a file name following the disk (ie anything
  640. * before the colon).
  641. * If there is no colon just return a pointer to the original string
  642. */
  643. LPTSTR RemoveDiskId(LPTSTR szPath)
  644. {
  645. LPTSTR sz;
  646. for (sz = szPath; *sz; sz++) {
  647. if (*sz == TEXT(':')) {
  648. return sz + 1;
  649. }
  650. }
  651. return szPath;
  652. }
  653. LPTSTR StripPathName(LPTSTR szPath)
  654. {
  655. LPTSTR sz;
  656. sz = FileName(szPath);
  657. if (sz > szPath+1 && SLASH(sz[-1]) && sz[-2] != TEXT(':'))
  658. sz--;
  659. *sz = 0;
  660. return szPath;
  661. }
  662. /*
  663. * See if a file is a kernel driver. Unfortunately the VersionInfo APIs
  664. * don't seem coded up to take care of this at the moment so we just check
  665. * to see if the file extension is ".SYS"
  666. */
  667. BOOL IsFileKernelDriver(LPTSTR szPath)
  668. {
  669. TCHAR drive[MAX_PATH];
  670. TCHAR dir[MAX_PATH];
  671. TCHAR fname[MAX_PATH];
  672. TCHAR ext[MAX_PATH];
  673. lsplitpath(szPath, drive, dir, fname, ext);
  674. return !_wcsicmp(ext, TEXT(".sys"));
  675. }
  676. /**************************************************************************
  677. *
  678. * This function converts returned flags from Ver API to the numerical
  679. * error codes used in SETUP.
  680. *
  681. ***************************************************************************/
  682. UINT ConvertFlagToValue(DWORD dwFlags)
  683. {
  684. if ( ! dwFlags )
  685. return(NO_ERROR);
  686. if ( dwFlags & VIF_CANNOTREADSRC )
  687. return(ERROR_FILE_NOT_FOUND);
  688. if ( dwFlags & VIF_OUTOFMEMORY )
  689. return(ERROR_OUTOFMEMORY);
  690. if ( dwFlags & VIF_ACCESSVIOLATION )
  691. return(ERROR_ACCESS_DENIED);
  692. if ( dwFlags & VIF_SHARINGVIOLATION )
  693. return(ERROR_SHARING_VIOLATION);
  694. if ( dwFlags & VIF_FILEINUSE)
  695. return(FC_ERROR_LOADED_DRIVER);
  696. return(ERROR_CANNOT_COPY); // General error
  697. }
  698. #ifdef CHECK_FLOPPY
  699. /*--------------------------------------------------------------------------
  700. IsValidDiskette() -
  701. --------------------------------------------------------------------------*/
  702. #define CBSECTORSIZE 512
  703. #define INT13_READ 2
  704. BOOL IsValidDiskette(int iDrive)
  705. {
  706. TCHAR buf[CBSECTORSIZE];
  707. iDrive |= 0x0020; // make lower case
  708. iDrive -= 'a'; // A = 0, B = 1, etc. for BIOS stuff
  709. return MyReadWriteSector(buf, INT13_READ, iDrive, 0, 0, 1);
  710. }
  711. /* BOOL IsDiskInDrive(char cDisk)
  712. *
  713. * Is the specifed disk in the drive
  714. *
  715. * ENTRY:
  716. *
  717. * cDisk : what disk required to be in the drive (logical)
  718. *
  719. * return TRUE if the specifed disk is in the drive
  720. * FALSE if the wrong disk is in the drive or disk error
  721. *
  722. */
  723. BOOL IsDiskInDrive(int iDisk)
  724. {
  725. if ((iDisk >= 'A' && iDisk <= 'Z') ||
  726. (iDisk >= 'a' && iDisk <= 'z'))
  727. {
  728. if (DosRemoveable(iDisk))
  729. {
  730. if (!IsValidDiskette(iDisk))
  731. return FALSE;
  732. }
  733. return TRUE;
  734. }
  735. return TRUE; // for non drive letters assume a path
  736. // and thus always in.
  737. }
  738. #endif