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.

939 lines
32 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* WFDCOPY.C - */
  4. /* */
  5. /* File Manager Diskette Copying Routines */
  6. /* */
  7. /****************************************************************************/
  8. #include "winfile.h"
  9. LONG APIENTRY LongPtrAdd(LPSTR, DWORD);
  10. PBPB GetBootBPB(INT nSrceDrive);
  11. PBPB GetBPB(INT nDrive, PDevPB pDevicePB);
  12. BOOL CheckBPBCompatibility(PBPB pSrceBPB, int nSrcDriveType, PBPB pDestBPB, int nDestDriveType);
  13. BOOL ModifyDeviceParams(
  14. INT nDrive,
  15. PDevPB pdpbParams,
  16. HANDLE *phSaveParams,
  17. PBPB pDriveBPB,
  18. PBPB pMediaBPB);
  19. BOOL FormatAllTracks(
  20. PDISKINFO pDisketteInfo,
  21. WORD wStartCylinder,
  22. WORD wStartHead,
  23. LPSTR lpDiskBuffer);
  24. BOOL AllocDiskCopyBuffers(PDISKINFO pDisketteInfo);
  25. VOID FreeBuffers(VOID);
  26. VOID GetDisketteInfo(PDISKINFO pDisketteInfo, PBPB pBPB);
  27. VOID DCopyMessageBox(HWND hwnd, WORD idString, WORD wFlags);
  28. VOID PromptDisketteChange(HWND hwnd, BOOL bWrite);
  29. INT ReadWriteMaxPossible(BOOL bWrite, WORD wStartCylinder, PDISKINFO pDisketteInfo);
  30. INT ReadWrite(BOOL bWrite, WORD wStartCylinder, PDISKINFO pDisketteInfo);
  31. BOOL RestoreDPB(INT nDisk, HANDLE hSavedParams);
  32. INT ReadWriteCylinder(BOOL bWrite, WORD wCylinder, PDISKINFO pDisketteInfo);
  33. /* The following structure is the Parameter block for the read-write
  34. * operations using the IOCTL calls in DOS
  35. */
  36. struct RW_PARMBLOCK {
  37. BYTE bSplFn;
  38. WORD wHead;
  39. WORD wCylinder;
  40. WORD wStSector;
  41. WORD wCount;
  42. LPSTR lpBuffer;
  43. };
  44. /* Global Variables */
  45. BOOL bFormatDone;
  46. BOOL bSingleDrive = TRUE;
  47. WORD wCompletedCylinders = 0;
  48. DWORD dwDisketteBufferSize;
  49. LPSTR lpDosMemory;
  50. LPSTR lpFormatBuffer;
  51. LPSTR lpReadWritePtr;
  52. LPSTR hpDisketteBuffer;
  53. HANDLE hFormatBuffer;
  54. HANDLE hDosMemory;
  55. HANDLE hDisketteBuffer;
  56. PDevPB pTrackLayout; /* DevPB with the track layout */
  57. BOOTSEC BootSec;
  58. /* External Variables */
  59. extern BPB bpbList[];
  60. /*--------------------------------------------------------------------------*/
  61. /* */
  62. /* GetBootBPB() - */
  63. /* */
  64. /*--------------------------------------------------------------------------*/
  65. /* This reads the boot sector of a floppy and returns a ptr to
  66. * the BIOS PARAMETER BLOCK in the Boot sector.
  67. */
  68. PBPB
  69. GetBootBPB(
  70. INT nSrceDrive
  71. )
  72. {
  73. INT rc;
  74. /* Make sure that the source diskette's boot sector is valid. */
  75. rc = GenericReadWriteSector((LPSTR)&BootSec, INT13_READ, (WORD)nSrceDrive, 0, 0, 1);
  76. if ((rc < 0) || ((BootSec.jump[0] != 0xE9) && (BootSec.jump[0] != 0xEB)))
  77. return (PBPB)NULL;
  78. return (PBPB)&(BootSec.BPB);
  79. }
  80. /*--------------------------------------------------------------------------*/
  81. /* */
  82. /* GetBPB() - */
  83. /* */
  84. /*--------------------------------------------------------------------------*/
  85. /* Gets get the BPB of the Physical Drive.
  86. *
  87. * This uses the IOCTL calls if DOS ver >= 3.2; Otherwise it uses the
  88. * BIOS calls to find out the drive type and picks us the BPB from a table.
  89. * It also returns the DeviceParameterBlock thro params if DOS >= 3.2.
  90. * Sets devType field of DeviceParameterBlock in any case (11.12.91) v-dougk
  91. */
  92. PBPB
  93. GetBPB(
  94. INT nDrive,
  95. PDevPB pDevicePB
  96. )
  97. {
  98. INT iDisketteType;
  99. PBPB pBPB = NULL;
  100. /* Check the DOS version */
  101. if (wDOSversion >= DOS_320) {
  102. /* All fields in pDevicePB must be initialized to zero. */
  103. memset(pDevicePB, 0, sizeof(DevPB));
  104. /* Spl Function field must be set to get parameters */
  105. pDevicePB->SplFunctions = 0;
  106. pBPB = &(pDevicePB->BPB);
  107. } else {
  108. /* Find out the Drive type using the BIOS. */
  109. if ((iDisketteType = GetDriveCapacity((WORD)nDrive)) == 0)
  110. goto GBPB_Error;
  111. /* Lookup this drive's default BPB. */
  112. pBPB = &bpbList[iDisketteType+2];
  113. switch (iDisketteType) {
  114. case 1:
  115. pDevicePB->devType = 0; // 360K
  116. break;
  117. case 2:
  118. pDevicePB->devType = 1; // 1.2M
  119. break;
  120. }
  121. }
  122. GBPB_Error:
  123. return (pBPB);
  124. }
  125. /*--------------------------------------------------------------------------*/
  126. /* */
  127. /* CheckBPBCompatibility() - */
  128. /* */
  129. /*--------------------------------------------------------------------------*/
  130. /* Checks whether the two BPB are compatible for the purpose of performing
  131. * the diskcopy operation.
  132. */
  133. BOOL
  134. CheckBPBCompatibility(
  135. PBPB pSrceBPB,
  136. int nSrcDriveType,
  137. PBPB pDestBPB,
  138. int nDestDriveType
  139. )
  140. {
  141. /* Let us compare the media byte */
  142. if (pSrceBPB->bMedia == 0xF9) {
  143. /* If the source and dest have the same number of sectors,
  144. * or if srce is 720KB and Dest is 1.44MB floppy drive,
  145. * thnigs are kosher.
  146. */
  147. if ((pSrceBPB->cSec == pDestBPB->cSec) ||
  148. ((pSrceBPB->secPerTrack == 9) && (pDestBPB -> bMedia == 0xF0)))
  149. return (TRUE);
  150. } else {
  151. /* If they have the same media byte */
  152. if ((pSrceBPB->bMedia == pDestBPB->bMedia) &&
  153. (pSrceBPB->cbSec == pDestBPB->cbSec) && // bytes per sector are the same
  154. (pSrceBPB->cSec == pDestBPB->cSec)) // total sectors on drive are the same
  155. return (TRUE); /* They are compatible */
  156. else if
  157. /* srce is 160KB and dest is 320KB drive */
  158. (((pSrceBPB->bMedia == MEDIA_160) && (pDestBPB->bMedia == MEDIA_320)) ||
  159. /* or if srce is 180KB and dest is 360KB drive */
  160. ((pSrceBPB->bMedia == MEDIA_180) && (pDestBPB->bMedia == MEDIA_360)) ||
  161. /* or if srce is 1.44MB and dest is 2.88MB drive */
  162. ((pSrceBPB->bMedia == MEDIA_1440) && (pDestBPB->bMedia == MEDIA_2880)
  163. && ((nSrcDriveType == 7) || (nSrcDriveType == 9))
  164. && (nDestDriveType == 9)) ||
  165. /* or if srce is 360KB and dest is 1.2MB drive */
  166. ((pSrceBPB->bMedia == MEDIA_360) && (pDestBPB->secPerTrack == 15)))
  167. return (TRUE); /* They are compatible */
  168. }
  169. /* All other combinations are currently incompatible. */
  170. return (FALSE);
  171. }
  172. /*--------------------------------------------------------------------------*/
  173. /* */
  174. /* ModifyDeviceParams() - */
  175. /* */
  176. /*--------------------------------------------------------------------------*/
  177. /* Saves a copy of the drive parameters block and
  178. * Checks if the BPB of Drive and BPB of disk are different and if
  179. * so, modifies the drive parameter block accordingly.
  180. */
  181. BOOL
  182. ModifyDeviceParams(
  183. INT nDrive,
  184. PDevPB pdpbParams,
  185. HANDLE *phSaveParams,
  186. PBPB pDriveBPB,
  187. PBPB pMediaBPB)
  188. {
  189. INT iDriveCode;
  190. HANDLE hNewDPB;
  191. PDevPB pNewDPB;
  192. if (!(*phSaveParams = BuildDevPB(pdpbParams)))
  193. return FALSE;
  194. /* Check if the Disk and Drive have the same parameters */
  195. if (pMediaBPB->bMedia != pDriveBPB->bMedia) {
  196. /* They are not equal; So, it must be a 360KB floppy in a 1.2MB drive
  197. * or a 720KB floppy in a 1.44MB drive kind of situation!.
  198. * So, modify the DriveParameterBlock's BPB.
  199. */
  200. *(PBPB)&(pdpbParams->BPB) = *pMediaBPB;
  201. }
  202. if (wDOSversion >= DOS_320) {
  203. /* Build a DPB with TrackLayout */
  204. if (!(hNewDPB = BuildDevPB(pdpbParams)))
  205. goto MDP_Error;
  206. pNewDPB = (PDevPB)LocalLock(hNewDPB);
  207. pNewDPB->SplFunctions = 4; /* To Set parameters */
  208. /* Check if this is a 360KB floppy; And if it is a 1.2MB drive, the
  209. * number of cylinders and mediatype field are wrong; So, we modify
  210. * these fields here anyway;
  211. * This is required to format a 360KB floppy on a NCR PC916 machine;
  212. * Fix for Bug #6894 --01-10-90-- SANKAR
  213. */
  214. if (pMediaBPB->bMedia == MEDIA_360) {
  215. pNewDPB->NumCyls = 40;
  216. pNewDPB->bMediaType = 1;
  217. }
  218. LocalUnlock(hNewDPB);
  219. LocalFree(hNewDPB);
  220. } else {
  221. iDriveCode = 0;
  222. switch (pMediaBPB->bMedia) {
  223. case MEDIA_360:
  224. case MEDIA_320:
  225. if ((pDriveBPB->bMedia == MEDIA_360) ||
  226. (pDriveBPB->bMedia == MEDIA_320))
  227. iDriveCode = 1; /* Must be 360/320KB in 360KB drive */
  228. else
  229. iDriveCode = 2; /* Must be 360/320Kb in 1.2MB drive */
  230. break;
  231. case MEDIA_1200:
  232. iDriveCode = 3; /* Must be 1.2MB in 1.2MB drive */
  233. break;
  234. }
  235. if (iDriveCode)
  236. SetDASD((WORD)nDrive, (BYTE)iDriveCode);
  237. }
  238. return (TRUE);
  239. /* Error handling */
  240. MDP_Error:
  241. if (hNewDPB)
  242. LocalFree(hNewDPB);
  243. if (*phSaveParams) {
  244. LocalFree(*phSaveParams);
  245. *phSaveParams = NULL;
  246. }
  247. return (FALSE);
  248. }
  249. /*--------------------------------------------------------------------------*/
  250. /* */
  251. /* FormatAllTracks() - */
  252. /* */
  253. /*--------------------------------------------------------------------------*/
  254. BOOL
  255. FormatAllTracks(
  256. PDISKINFO pDisketteInfo,
  257. WORD wStartCylinder,
  258. WORD wStartHead,
  259. LPSTR lpDiskBuffer)
  260. {
  261. INT iErrCode;
  262. BOOL bRetValue = TRUE;
  263. WORD wTotalCylinders;
  264. WORD wSecPerTrack;
  265. WORD wHeads;
  266. WORD wDrive;
  267. LoadString(hAppInstance, IDS_FORMATTINGDEST, szMessage, 128);
  268. SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage);
  269. bFormatDone = TRUE;
  270. wDrive = pDisketteInfo->wDrive;
  271. if (wDOSversion >= DOS_320) {
  272. pTrackLayout->SplFunctions = 5;
  273. } else {
  274. if ((pTrackLayout->BPB.bMedia == 0xF9) && /* high density */
  275. (pTrackLayout->BPB.secPerTrack == 15)) /* 1.2 Meg Drive */
  276. SetDASD(wDrive, 3); /* 1.2 MB floppy in 1.2MB drive */
  277. }
  278. wTotalCylinders = pDisketteInfo->wLastCylinder + 1;
  279. wSecPerTrack = pDisketteInfo->wSectorsPerTrack;
  280. wHeads = pDisketteInfo->wHeads;
  281. /* Format tracks one by one, checking if the user has "Aborted"
  282. * after each track is formatted; DlgProgreeProc() will set the global
  283. * bUserAbort, if the user has aborted;
  284. */
  285. while (wStartCylinder < wTotalCylinders) {
  286. /* Has the user aborted? */
  287. if (WFQueryAbort()) {
  288. bRetValue = FALSE;
  289. break;
  290. }
  291. /* If no message is pending, go ahead and format one track */
  292. if ((iErrCode = GenericFormatTrack(wDrive, wStartCylinder, wStartHead, wSecPerTrack, lpDiskBuffer))) {
  293. /* Check if it is a fatal error */
  294. if (iErrCode == -1) {
  295. bRetValue = FALSE;
  296. break;
  297. }
  298. }
  299. if (++wStartHead >= wHeads) {
  300. wStartHead = 0;
  301. wStartCylinder++;
  302. }
  303. }
  304. if (wDOSversion >= DOS_320) {
  305. pTrackLayout->SplFunctions = 4;
  306. }
  307. return (bRetValue);
  308. }
  309. /*--------------------------------------------------------------------------*/
  310. /* */
  311. /* GenericReadWriteSector() - */
  312. /* */
  313. /*--------------------------------------------------------------------------*/
  314. /* Checks the DOS version number; If it is >= 3.2, then IOCTL
  315. * calls are made to read/write; Else it calls int13 read/write.
  316. */
  317. INT
  318. APIENTRY
  319. GenericReadWriteSector(
  320. LPSTR lpBuffer,
  321. WORD wFunction,
  322. WORD wDrive,
  323. WORD wCylinder,
  324. WORD wHead,
  325. WORD wCount)
  326. {
  327. struct RW_PARMBLOCK RW_ParmBlock;
  328. /* If the DOS version is >= 3.2, we use DOS IOCTL function calls. */
  329. if (wDOSversion >= DOS_320) {
  330. RW_ParmBlock.bSplFn = 0;
  331. RW_ParmBlock.wHead = wHead;
  332. RW_ParmBlock.wCylinder = wCylinder;
  333. RW_ParmBlock.wStSector = 0;
  334. RW_ParmBlock.wCount = wCount;
  335. RW_ParmBlock.lpBuffer = lpBuffer;
  336. return (0);
  337. } else
  338. /* Use Int13 function calls. */
  339. return (MyReadWriteSector(lpBuffer, wFunction, wDrive, wCylinder, wHead, wCount));
  340. }
  341. /*--------------------------------------------------------------------------*/
  342. /* */
  343. /* AllocDiskCopyBuffers() - */
  344. /* */
  345. /*--------------------------------------------------------------------------*/
  346. BOOL
  347. AllocDiskCopyBuffers(
  348. PDISKINFO pDisketteInfo
  349. )
  350. {
  351. HANDLE hMemTemp;
  352. ENTER("AllocDiskCopyBuffers");
  353. hFormatBuffer = LocalAlloc(LHND, (LONG)(2*CBSECTORSIZE));
  354. if (!hFormatBuffer)
  355. return FALSE;
  356. lpFormatBuffer = (LPSTR)LocalLock(hFormatBuffer);
  357. // We will try to reserve 16K for dialog boxes that comeup during diskcopy
  358. hMemTemp = LocalAlloc(LHND, (16 * 1024));
  359. if (!hMemTemp)
  360. goto Failure;
  361. hDosMemory = (HANDLE)NULL;
  362. // now, lets try to allocate a buffer for the whole disk, and
  363. // if that fails try smaller
  364. // note, standard mode will only give us 1M chuncks
  365. dwDisketteBufferSize = pDisketteInfo->wCylinderSize * (pDisketteInfo->wLastCylinder + 1);
  366. // we will try down to 8 cylinders worth, less than that means
  367. // there will be too much disk swapping so don't bother
  368. do {
  369. hDisketteBuffer = LocalAlloc(LHND, dwDisketteBufferSize);
  370. if (hDisketteBuffer) {
  371. hpDisketteBuffer = (LPSTR)LocalLock(hDisketteBuffer);
  372. break;
  373. } else {
  374. // reduce request by 4 cylinders.
  375. dwDisketteBufferSize -= pDisketteInfo->wCylinderSize * 4;
  376. }
  377. } while (dwDisketteBufferSize > (DWORD)(8 * pDisketteInfo->wCylinderSize));
  378. LocalFree(hMemTemp); // now free this up for user
  379. if (hDisketteBuffer)
  380. return TRUE;
  381. // fall through here to the failure case
  382. Failure:
  383. if (lpFormatBuffer) {
  384. LocalUnlock(hFormatBuffer);
  385. LocalFree(hFormatBuffer);
  386. }
  387. if (hDosMemory)
  388. // +++GlobalDosFree - NO 32BIT FORM+++(hDosMemory);
  389. LocalFree(hDosMemory);
  390. LEAVE("AllocDiskCopyBuffers");
  391. return FALSE;
  392. }
  393. /*--------------------------------------------------------------------------*/
  394. /* */
  395. /* FreeBuffers() - */
  396. /* */
  397. /*--------------------------------------------------------------------------*/
  398. VOID
  399. FreeBuffers()
  400. {
  401. if (lpFormatBuffer) {
  402. LocalUnlock(hFormatBuffer);
  403. LocalFree(hFormatBuffer);
  404. }
  405. if (hDosMemory)
  406. // +++GlobalDosFree - NO 32BIT FORM+++(hDosMemory);
  407. LocalFree(hDosMemory);
  408. if (hpDisketteBuffer) {
  409. LocalUnlock(hDisketteBuffer);
  410. LocalFree(hDisketteBuffer);
  411. }
  412. }
  413. /*--------------------------------------------------------------------------*/
  414. /* */
  415. /* GetDisketteInfo() - */
  416. /* */
  417. /*--------------------------------------------------------------------------*/
  418. VOID
  419. GetDisketteInfo(
  420. PDISKINFO pDisketteInfo,
  421. PBPB pBPB
  422. )
  423. {
  424. WORD secPerTrack;
  425. secPerTrack = pBPB->secPerTrack;
  426. /* Fill the DisketteInfo with the info from the default BPB. */
  427. pDisketteInfo->wCylinderSize = secPerTrack * pBPB->cbSec * pBPB->cHead;
  428. pDisketteInfo->wLastCylinder = (pBPB->cSec / (secPerTrack * pBPB->cHead))-1;
  429. pDisketteInfo->wHeads = pBPB->cHead;
  430. pDisketteInfo->wSectorsPerTrack = secPerTrack;
  431. pDisketteInfo->wSectorSize = pBPB->cbSec;
  432. }
  433. /*--------------------------------------------------------------------------*/
  434. /* */
  435. /* DCopyMessageBox() - */
  436. /* */
  437. /*--------------------------------------------------------------------------*/
  438. VOID
  439. DCopyMessageBox(
  440. HWND hwnd,
  441. WORD idString,
  442. WORD wFlags
  443. )
  444. {
  445. LoadString(hAppInstance, IDS_COPYDISK, szTitle, sizeof(szTitle));
  446. LoadString(hAppInstance, idString, szMessage, sizeof(szMessage));
  447. MessageBox(hwnd, szMessage, szTitle, wFlags);
  448. }
  449. /*--------------------------------------------------------------------------*/
  450. /* */
  451. /* PromptDisketteChange() - */
  452. /* */
  453. /*--------------------------------------------------------------------------*/
  454. VOID
  455. PromptDisketteChange(
  456. HWND hwnd,
  457. BOOL bWrite
  458. )
  459. {
  460. WORD idString;
  461. if (bWrite)
  462. idString = IDS_INSERTDEST;
  463. else
  464. idString = IDS_INSERTSRC;
  465. /* These dialogs have to be sysmodal because the DiskCopy progress dialog
  466. * is now made a SysModal one; The following messagebox will hang if it
  467. * is NOT sysmodal;
  468. * A part of the Fix for Bug #10075 --SANKAR-- 03-05-90
  469. */
  470. DCopyMessageBox(hwnd, idString, MB_OK | MB_SYSTEMMODAL | MB_ICONINFORMATION);
  471. }
  472. /*--------------------------------------------------------------------------*/
  473. /* */
  474. /* ReadWriteCylinder() - */
  475. // BOOL bWrite; TRUE for Write, FALSE for Read
  476. /* */
  477. /*--------------------------------------------------------------------------*/
  478. INT
  479. ReadWriteCylinder(
  480. BOOL bWrite,
  481. WORD wCylinder,
  482. PDISKINFO pDisketteInfo
  483. )
  484. {
  485. register INT rc;
  486. WORD wHead;
  487. WORD wDrive;
  488. WORD wSectorCount;
  489. WORD wTrackSize;
  490. LPSTR lpBuffer;
  491. wDrive = pDisketteInfo->wDrive;
  492. wSectorCount = pDisketteInfo->wSectorsPerTrack;
  493. wTrackSize = (wSectorCount * pDisketteInfo->wSectorSize);
  494. if (hDosMemory)
  495. lpBuffer = lpDosMemory;
  496. /* Perform the operation for all the heads for a given cylinder */
  497. for (wHead=0; wHead < pDisketteInfo->wHeads; wHead++) {
  498. if (!hDosMemory)
  499. lpBuffer = lpReadWritePtr;
  500. if (bWrite) {
  501. if (hDosMemory)
  502. memcpy(lpBuffer, lpReadWritePtr, wTrackSize);
  503. rc = GenericReadWriteSector((LPSTR)lpBuffer,
  504. INT13_WRITE,
  505. wDrive,
  506. wCylinder,
  507. wHead,
  508. wSectorCount);
  509. if (rc) {
  510. /* Format all tracks starting from the given track */
  511. if (!bFormatDone) {
  512. if (!FormatAllTracks(pDisketteInfo, wCylinder, wHead, lpFormatBuffer))
  513. return (-1); /* Failure */
  514. rc = GenericReadWriteSector((LPSTR)lpBuffer,
  515. INT13_WRITE,
  516. wDrive,
  517. wCylinder,
  518. wHead,
  519. wSectorCount);
  520. } else
  521. break;
  522. }
  523. } else {
  524. rc = GenericReadWriteSector((LPSTR)lpBuffer,
  525. INT13_READ,
  526. wDrive,
  527. wCylinder,
  528. wHead,
  529. wSectorCount);
  530. if (hDosMemory)
  531. memcpy(lpReadWritePtr, lpBuffer, wTrackSize);
  532. /*** FIX30: What about the DOS 4.0 volume stuff??? ***/
  533. }
  534. if (rc)
  535. return (-1);
  536. lpReadWritePtr += wTrackSize;
  537. }
  538. return (0);
  539. }
  540. /*--------------------------------------------------------------------------*/
  541. /* */
  542. /* ReadWriteMaxPossible() - */
  543. // BOOL bWrite TRUE for Write, FALSE for Read
  544. /* */
  545. /*--------------------------------------------------------------------------*/
  546. /* This reads or writes as many cylinders as possible into the hpDisketteBuffer.
  547. * It returns the next cylinder to be read.
  548. */
  549. INT
  550. ReadWriteMaxPossible(
  551. BOOL bWrite,
  552. WORD wStartCylinder,
  553. PDISKINFO pDisketteInfo
  554. )
  555. {
  556. MSG msg;
  557. WORD wPercentDone;
  558. DWORD dwBufferSize;
  559. dwBufferSize = dwDisketteBufferSize;
  560. /* We will read a cylinder only if we can read the entire cylinder. */
  561. while (dwBufferSize >= pDisketteInfo->wCylinderSize) {
  562. /* Check if any messages are pending */
  563. if (!PeekMessage((LPMSG)&msg, (HWND)NULL, 0, 0, PM_REMOVE)) {
  564. /* No message; So, go ahead with read/write */
  565. if (ReadWriteCylinder(bWrite, wStartCylinder, pDisketteInfo))
  566. return (-1);
  567. wStartCylinder++;
  568. wCompletedCylinders++;
  569. /* Have we read/written all the cylinders? */
  570. if (wStartCylinder > pDisketteInfo->wLastCylinder)
  571. break;
  572. /* Since each cylinder is counted once during read and once during
  573. * write, number of cylinders is multiplied by 50 and not 100.
  574. */
  575. wPercentDone = (wCompletedCylinders * 50) / (pDisketteInfo->wLastCylinder + 1);
  576. if (LoadString(hAppInstance, IDS_PERCENTCOMP, szTitle, 32)) {
  577. wsprintf(szMessage, szTitle, wPercentDone);
  578. SendDlgItemMessage(hdlgProgress, IDD_PROGRESS, WM_SETTEXT, 0, (LPARAM)szMessage);
  579. }
  580. dwBufferSize -= pDisketteInfo->wCylinderSize;
  581. } else {
  582. /* Check if this is a message for the ProgressDlg */
  583. if (!IsDialogMessage(hdlgProgress, &msg)) {
  584. TranslateMessage(&msg);
  585. DispatchMessage(&msg);
  586. } else {
  587. /* That message might have resulted in a Abort */
  588. if (bUserAbort)
  589. return (-1);
  590. }
  591. }
  592. }
  593. return (wStartCylinder);
  594. }
  595. /*--------------------------------------------------------------------------*/
  596. /* */
  597. /* ReadWrite() - */
  598. // BOOL bWrite TRUE for Write, FALSE for Read
  599. /* */
  600. /*--------------------------------------------------------------------------*/
  601. /* This reads or writes as many cylinders as possible into the hpDisketteBuffer.
  602. * It returns the next cylinder to be read.
  603. */
  604. INT
  605. ReadWrite(
  606. BOOL bWrite,
  607. WORD wStartCylinder,
  608. PDISKINFO pDisketteInfo
  609. )
  610. {
  611. INT iRetVal = 0;
  612. return (iRetVal);
  613. }
  614. /*--------------------------------------------------------------------------*/
  615. /* */
  616. /* RestoreDPB() - */
  617. /* */
  618. /*--------------------------------------------------------------------------*/
  619. BOOL
  620. RestoreDPB(
  621. INT nDisk,
  622. HANDLE hSavedParams
  623. )
  624. {
  625. register PDevPB pDevPB;
  626. if (!(pDevPB = (PDevPB)LocalLock(hSavedParams)))
  627. return (FALSE);
  628. pDevPB->SplFunctions = 4;
  629. LocalUnlock(hSavedParams);
  630. LocalFree(hSavedParams);
  631. return (TRUE);
  632. }
  633. /*--------------------------------------------------------------------------*/
  634. /* */
  635. /* CopyDiskette() - */
  636. /* */
  637. /*--------------------------------------------------------------------------*/
  638. /* NOTE: Returns positive value for success otherwise failure. */
  639. INT
  640. APIENTRY
  641. CopyDiskette(
  642. HWND hwnd,
  643. WORD nSourceDisk,
  644. WORD nDestDisk
  645. )
  646. {
  647. INT rc = -1;
  648. register WORD wCylinder;
  649. WORD wNextCylinder;
  650. PBPB pIoctlBPB; /* Source Drive's BPB (taken from DevicePB) */
  651. PBPB pBootBPB; /* Boot Drive's BPB (taken from Boot sector) */
  652. PBPB pDestBPB;
  653. DevPB dpbSrceParams;
  654. DevPB dpbDestParams;
  655. HANDLE hTrackLayout = NULL;
  656. HANDLE hSaveSrceParams;
  657. HANDLE hSaveDestParams;
  658. FARPROC lpfnDialog;
  659. DISKINFO SourceDisketteInfo;
  660. DISKINFO DestDisketteInfo;
  661. /* Check if it is a two drive system; put message to insert both floppies */
  662. if (nSourceDisk != nDestDisk) {
  663. bSingleDrive = FALSE;
  664. DCopyMessageBox(hwnd, IDS_INSERTSRCDEST, MB_OK);
  665. } else {
  666. bSingleDrive = TRUE;
  667. DCopyMessageBox(hwnd, IDS_INSERTSRC, MB_OK);
  668. }
  669. /* Get the BiosParameterBlock of source drive */
  670. if (!(pIoctlBPB = GetBPB(nSourceDisk, &dpbSrceParams)))
  671. return (0);
  672. /* Get the BiosParameterBlock of the Source Diskette */
  673. if (!(pBootBPB = GetBootBPB(nSourceDisk)))
  674. return (0);
  675. /* Get the BPB and DPB for the Destination drive also; */
  676. if (!bSingleDrive) {
  677. if (!(pDestBPB = GetBPB(nDestDisk, &dpbDestParams)))
  678. return (0);
  679. /* Compare BPB of source and Dest to see if they are compatible */
  680. if (!(CheckBPBCompatibility(pIoctlBPB, dpbSrceParams.devType, pDestBPB, dpbDestParams.devType))) {
  681. DCopyMessageBox(hwnd, IDS_COPYSRCDESTINCOMPAT, MB_ICONHAND | MB_OK);
  682. return (0);
  683. }
  684. }
  685. if (!ModifyDeviceParams(nSourceDisk, &dpbSrceParams, &hSaveSrceParams, pIoctlBPB, pBootBPB))
  686. return (0);
  687. if (!bSingleDrive) {
  688. if (!ModifyDeviceParams(nDestDisk, &dpbDestParams, &hSaveDestParams, pDestBPB, pBootBPB)) {
  689. RestoreDPB(nSourceDisk, hSaveSrceParams);
  690. return (0);
  691. }
  692. }
  693. GetDisketteInfo((PDISKINFO)&SourceDisketteInfo, pBootBPB);
  694. /* The Destination Diskette must have the same format as the source */
  695. DestDisketteInfo = SourceDisketteInfo;
  696. /* Except the drive number */
  697. SourceDisketteInfo.wDrive = nSourceDisk;
  698. DestDisketteInfo.wDrive = nDestDisk;
  699. /* In case we need to format the destination diskette, we need to know the
  700. * track layout; So, build a DPB with the required track layout;
  701. */
  702. if (wDOSversion >= DOS_320) {
  703. if (!(hTrackLayout = BuildDevPB(&dpbSrceParams)))
  704. goto Failure0;
  705. pTrackLayout = (PDevPB)LocalLock(hTrackLayout);
  706. /* The following is required to format a 360KB floppy in a 1.2MB
  707. * drive of NCR PC916 machine; We do formatting, if the destination
  708. * floppy is an unformatted one;
  709. * Fix for Bug #6894 --01-10-90-- SANKAR --
  710. */
  711. if (pTrackLayout->BPB.bMedia == MEDIA_360) {
  712. pTrackLayout->NumCyls = 40;
  713. pTrackLayout->bMediaType = 1;
  714. }
  715. }
  716. /* We wish we could do the following allocation at the begining of this
  717. * function, but we can not do so, because we need SourceDisketteInfo
  718. * and we just got it;
  719. */
  720. if (!AllocDiskCopyBuffers((PDISKINFO)&SourceDisketteInfo)) {
  721. DCopyMessageBox(hwnd, IDS_REASONS+DE_INSMEM, MB_ICONHAND | MB_OK);
  722. goto Failure0;
  723. }
  724. bUserAbort = FALSE;
  725. wCompletedCylinders = 0;
  726. hdlgProgress = CreateDialog(hAppInstance, (LPSTR)MAKEINTRESOURCE(DISKCOPYPROGRESSDLG), hwnd, ProgressDlgProc);
  727. if (!hdlgProgress)
  728. goto Failure2;
  729. EnableWindow(hwnd, FALSE);
  730. /* Start with the first cylinder. */
  731. wCylinder = 0;
  732. while (wCylinder <= SourceDisketteInfo.wLastCylinder) {
  733. /* If this is a single drive system, ask the user to insert
  734. * the source diskette.
  735. * Do not prompt for the first time, because the Source diskette is
  736. * already in the drive.
  737. */
  738. if (bSingleDrive && (wCylinder > 0))
  739. PromptDisketteChange(hdlgProgress, FALSE);
  740. /* Read in the current cylinder. */
  741. rc = ReadWrite(FALSE, wCylinder, (PDISKINFO)&SourceDisketteInfo);
  742. if (rc < 0)
  743. break;
  744. else
  745. wNextCylinder = (WORD)rc;
  746. /* If this is a single drive system, ask the user to insert
  747. * the destination diskette.
  748. */
  749. if (bSingleDrive)
  750. PromptDisketteChange(hdlgProgress, TRUE);
  751. /* Write out the current cylinder. */
  752. bFormatDone = FALSE;
  753. rc = ReadWrite(TRUE, wCylinder, (PDISKINFO)&DestDisketteInfo);
  754. if (rc < 0)
  755. break;
  756. wCylinder = wNextCylinder;
  757. }
  758. EnableWindow(hwnd, TRUE);
  759. DestroyWindow(hdlgProgress);
  760. hdlgProgress = NULL;
  761. Failure2:
  762. FreeBuffers();
  763. Failure0:
  764. if (wDOSversion >= DOS_320) {
  765. /* Reset the Source drive parameters to the same as old */
  766. RestoreDPB(nSourceDisk, hSaveSrceParams);
  767. if (!bSingleDrive) {
  768. /* Reset the Dest drive parameters to the same as old */
  769. RestoreDPB(nDestDisk, hSaveDestParams);
  770. }
  771. }
  772. if ((wDOSversion >= DOS_320) && hTrackLayout) {
  773. LocalUnlock(hTrackLayout);
  774. LocalFree(hTrackLayout);
  775. }
  776. return (rc);
  777. }