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.

1198 lines
34 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: layout.cxx
  7. //
  8. // Contents: Code for the relayout tool
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-Feb-96 PhilipLa Created
  15. // 21-Feb-96 SusiA Put funtions on ILayoutStorage
  16. //
  17. //----------------------------------------------------------------------------
  18. #include "layouthd.cxx"
  19. #pragma hdrstop
  20. #include <dirfunc.hxx>
  21. #include "laylkb.hxx"
  22. #include "laywrap.hxx"
  23. #include <stddef.h>
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: CLayoutRootStorage::LayoutScript
  27. //
  28. // Synopsis: Construct an unprocessed script from an app provided script
  29. //
  30. // Arguments: [pStorageLayout] -- Pointer to storage layout array
  31. // [nEntries] -- Number of entries in the array
  32. // [grfInterleavedFlag] -- Specifies disposition of control
  33. // structures
  34. //
  35. // Returns: Appropriate status code
  36. //
  37. // History: 21-Feb-96 SusiA Created
  38. //
  39. //----------------------------------------------------------------------------
  40. STDMETHODIMP CLayoutRootStorage::LayoutScript( StorageLayout *pStorageLayout,
  41. DWORD nEntries,
  42. DWORD glfInterleavedFlag)
  43. {
  44. SCODE sc;
  45. if ((LONG)nEntries < 0)
  46. {
  47. return E_INVALIDARG;
  48. }
  49. if ((LONG)nEntries == 0)
  50. {
  51. return S_OK;
  52. }
  53. if ((glfInterleavedFlag != STG_LAYOUT_INTERLEAVED) &&
  54. (glfInterleavedFlag != STG_LAYOUT_SEQUENTIAL ) )
  55. {
  56. return STG_E_INVALIDFLAG;
  57. }
  58. if (pStorageLayout == NULL)
  59. {
  60. return STG_E_INVALIDPOINTER;
  61. }
  62. if (FAILED(sc = BeginMonitor()))
  63. {
  64. return sc;
  65. }
  66. if (FAILED(sc = ProcessLayout(pStorageLayout,
  67. nEntries,
  68. glfInterleavedFlag)))
  69. {
  70. // ignore errors from EndMonitor
  71. EndMonitor();
  72. return sc;
  73. }
  74. if (FAILED(sc = EndMonitor()))
  75. {
  76. return sc;
  77. }
  78. return ResultFromScode(sc);
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Function: CLayoutRootStorage::BeginMonitor
  83. //
  84. // Synopsis: Begin monitoring the ILockBytes operations for recording a
  85. // script.
  86. //
  87. // Arguments: None.
  88. //
  89. // Returns: Appropriate status code
  90. //
  91. // History: 21-Feb-96 SusiA Created
  92. //
  93. //----------------------------------------------------------------------------
  94. STDMETHODIMP CLayoutRootStorage::BeginMonitor(void)
  95. {
  96. SCODE sc = S_OK;
  97. sc = _pllkb->StartLogging();
  98. return ResultFromScode(sc);
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Function: CLayoutRootStorage::EndMonitor
  103. //
  104. // Synopsis: Stop monitoring ILockBytes operations for script recording.
  105. //
  106. // Arguments: None.
  107. //
  108. // Returns: Appropriate status code
  109. //
  110. // History: 21-Feb-96 SusiA Created
  111. //
  112. //----------------------------------------------------------------------------
  113. STDMETHODIMP CLayoutRootStorage::EndMonitor(void)
  114. {
  115. SCODE sc = S_OK;
  116. sc = _pllkb->StopLogging();
  117. return ResultFromScode(sc);
  118. }
  119. //+---------------------------------------------------------------------------
  120. //
  121. // Function: CLayoutRootStorage::ReLayoutDocfile
  122. //
  123. // Synopsis: Relayout the docfile into the new name specified.
  124. //
  125. // Arguments: [pwcsNewName] -- Name of destination file
  126. //
  127. // Returns: Appropriate status code
  128. //
  129. // History: 13-Feb-96 PhilipLa Created
  130. // 21-Feb-96 SusiA Made a method on ILayoutStorage
  131. //
  132. //----------------------------------------------------------------------------
  133. STDMETHODIMP CLayoutRootStorage::ReLayoutDocfile(OLECHAR *pwcsNewDfName)
  134. {
  135. SCODE sc;
  136. #if (!defined(UNICODE) && (!defined(_MAC)))
  137. WCHAR awcScriptName[MAX_PATH + 1];
  138. UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  139. if (!MultiByteToWideChar(
  140. uCodePage,
  141. 0,
  142. _pllkb->GetScriptName(),
  143. -1,
  144. awcScriptName,
  145. MAX_PATH + 1
  146. ))
  147. {
  148. return STG_E_INVALIDNAME;
  149. }
  150. sc = StgLayoutDocfile(_pllkb->GetHandle(),
  151. pwcsNewDfName,
  152. awcScriptName);
  153. #else
  154. sc = StgLayoutDocfile(_pllkb->GetHandle(),
  155. pwcsNewDfName,
  156. _pllkb->GetScriptName());
  157. #endif //UNICODE
  158. if (FAILED(sc))
  159. {
  160. //Delete new file
  161. #ifdef UNICODE
  162. DeleteFileW(pwcsNewDfName);
  163. #elif defined( _MAC)
  164. DeleteFile(pwcsNewDfName);
  165. #else
  166. TCHAR atcPath[MAX_PATH + 1];
  167. uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  168. //Note: Intentionally ignore an error if it happens here. We
  169. // want to return the error from StgLayoutDocfile, not from
  170. // the cleanup path.
  171. WideCharToMultiByte(
  172. uCodePage,
  173. 0,
  174. pwcsNewDfName,
  175. -1,
  176. atcPath,
  177. _MAX_PATH + 1,
  178. NULL,
  179. NULL);
  180. DeleteFileA(atcPath);
  181. #endif // UNICODE
  182. }
  183. else
  184. {
  185. //Delete Script File
  186. DeleteFile(_pllkb->GetScriptName());
  187. //Note: Intentionally ignore an error if it happens here. We
  188. // want to return the error from StgLayoutDocfile, not from
  189. // the cleanup path.
  190. _pllkb->ClearScriptName();
  191. }
  192. return sc;
  193. }
  194. #if DBG == 1
  195. STDMETHODIMP CLayoutRootStorage::GetScript(TCHAR **ptcsScriptFileName)
  196. {
  197. *ptcsScriptFileName = _pllkb->GetScriptName();
  198. return S_OK;
  199. }
  200. #endif
  201. //+---------------------------------------------------------------------------
  202. //
  203. // Function: CLayoutRootStorage::ReLayoutDocfileOnILockBytes
  204. //
  205. // Synopsis: Relayout the docfile into a generic ILockBytes implementation.
  206. //
  207. // Arguments: [pILockBytes] -- destination relayout ILockBytes
  208. //
  209. // Returns: Appropriate status code
  210. //
  211. // History: 09-Jun-96 SusiA Created
  212. //
  213. //----------------------------------------------------------------------------
  214. STDMETHODIMP CLayoutRootStorage::ReLayoutDocfileOnILockBytes(ILockBytes *pILockBytes)
  215. {
  216. return STG_E_UNIMPLEMENTEDFUNCTION;
  217. }
  218. //+---------------------------------------------------------------------------
  219. //
  220. // Function: StgLayoutDocfile
  221. //
  222. // Synopsis: Given an old file and an unprocessed script, relayout the
  223. // docfile into the new name specified.
  224. //
  225. // Arguments: [hOld] -- Handle of source file
  226. // [pwcsNewDfName] -- Name of destination file
  227. // [pwcsScriptName] -- Name of unprocessed script file
  228. //
  229. // Returns: Appropriate status code
  230. //
  231. // History: 13-Feb-96 PhilipLa Created
  232. //
  233. //----------------------------------------------------------------------------
  234. SCODE StgLayoutDocfile(HANDLE hOld,
  235. OLECHAR const *pwcsNewDfName,
  236. OLECHAR const *pwcsScriptName)
  237. {
  238. SCODE sc = S_OK;
  239. CMappedFile mfOld, mfNew, mfScript;
  240. MAPFILE *pvOld, *pvNew, *pvScript;
  241. ULONG ulScriptSize;
  242. ULONG csectScript, csectProcessed, csectFile;
  243. ULONG cbSectorSize;
  244. ULONG i;
  245. SECT *psProcessedScript = NULL;
  246. if (pwcsNewDfName == NULL)
  247. return STG_E_INVALIDNAME;
  248. #ifdef _MAC
  249. layChkTo(EH_End, mfOld.InitFromHandle(hOld,
  250. GENERIC_READ,
  251. FALSE,
  252. NULL));
  253. #else
  254. layChkTo(EH_End, mfOld.InitFromHandle(hOld,
  255. GENERIC_READ,
  256. TRUE,
  257. NULL));
  258. #endif
  259. layChkTo(EH_End, mfNew.Init(pwcsNewDfName,
  260. mfOld.GetSize(),
  261. GENERIC_READ | GENERIC_WRITE,
  262. CREATE_ALWAYS,
  263. NULL));
  264. if ((pwcsScriptName !=NULL) &&
  265. (pwcsScriptName[0] != TEXT('\0')) )
  266. {
  267. sc = mfScript.Init(pwcsScriptName,
  268. 0,
  269. GENERIC_READ,
  270. OPEN_EXISTING,
  271. NULL);
  272. layChkTo(EH_End, sc);
  273. if (sc == STG_S_FILEEMPTY)
  274. {
  275. pvScript = NULL;
  276. }
  277. else
  278. {
  279. pvScript = &mfScript;
  280. }
  281. }
  282. else
  283. {
  284. pvScript = NULL;
  285. }
  286. pvOld = &mfOld;
  287. pvNew = &mfNew;
  288. //From this point on, we may get an exception while we're poking around
  289. // in one of the memory maps. We need to handle this case and be able
  290. // to properly return an error and clean up if it happens.
  291. #ifndef _MAC
  292. __try
  293. {
  294. #endif
  295. //Figure out how many sectors are in the file
  296. cbSectorSize = 1 << pvOld->GetUSHORT(
  297. (ULONG) offsetof(CMSFHeaderData,_uSectorShift));
  298. pvOld->SetSectorSize(cbSectorSize);
  299. pvNew->SetSectorSize(cbSectorSize);
  300. const ULONG cbHeader = cbSectorSize;
  301. csectFile = (mfOld.GetSize() + cbSectorSize - 1 -
  302. cbHeader) / cbSectorSize;
  303. SECT sectRangeLocks = (OLOCKREGIONEND - cbHeader + cbSectorSize - 1)
  304. / cbSectorSize;
  305. if (pvScript)
  306. {
  307. ulScriptSize = mfScript.GetSize();
  308. }
  309. else
  310. {
  311. ulScriptSize = 0;
  312. }
  313. csectProcessed = max(ulScriptSize / sizeof(SECT), csectFile);
  314. layMem(psProcessedScript = new SECT[csectProcessed]);
  315. for (i = 0; i < csectProcessed; i++)
  316. {
  317. psProcessedScript[i] = ENDOFCHAIN;
  318. }
  319. ULONG csectControl;
  320. layChk(ProcessControl(psProcessedScript,
  321. pvOld,
  322. &csectControl));
  323. layChk(ProcessScript(psProcessedScript,
  324. pvScript,
  325. csectFile,
  326. ulScriptSize / sizeof(SECT),
  327. csectControl,
  328. sectRangeLocks,
  329. &csectScript));
  330. //layAssert(csectScript == csectFile);
  331. layChk(CopyData(pvNew,
  332. pvOld,
  333. psProcessedScript,
  334. csectFile,
  335. cbSectorSize));
  336. layChk(RemapHeader(pvNew, psProcessedScript, csectFile));
  337. layChk(RemapDIF(pvNew, psProcessedScript, csectFile, cbSectorSize));
  338. layChk(RemapFat(pvNew,
  339. pvOld,
  340. psProcessedScript,
  341. csectFile,
  342. cbSectorSize));
  343. layChk(RemapDirectory(pvNew,
  344. psProcessedScript,
  345. csectFile,
  346. cbSectorSize));
  347. Err:
  348. delete [] psProcessedScript;
  349. #ifndef _MAC
  350. }
  351. __except (EXCEPTION_EXECUTE_HANDLER)
  352. {
  353. sc = STG_E_WRITEFAULT;
  354. }
  355. #endif
  356. pvOld = NULL;
  357. pvNew = NULL;
  358. EH_End:
  359. return sc;
  360. }
  361. //+---------------------------------------------------------------------------
  362. //
  363. // Function: GetDIFSect
  364. //
  365. // Synopsis: Return a pointer to the appropriate sector in the DIF
  366. //
  367. // Arguments: [pvBase] -- Pointer to base address of memory mapped file
  368. // [iDIF] -- Index into DIF desired
  369. // [cbSectorSize] -- Size in bytes of sector
  370. //
  371. // Returns: Pointer to appropriate sector
  372. //
  373. // History: 13-Feb-96 PhilipLa Created
  374. //
  375. //----------------------------------------------------------------------------
  376. CFatSect * GetDIFSect(MAPFILE *pvBase,
  377. ULONG iDIF,
  378. ULONG cbSectorSize,
  379. SECT *psect)
  380. {
  381. USHORT cSectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
  382. SECT sectDif = pvBase->GetULONG(
  383. (ULONG) offsetof(CMSFHeaderData,_sectDifStart));
  384. for (ULONG i = 0; i < iDIF; i++)
  385. {
  386. CFatSect *pdif = pvBase->GetCFatSect((sectDif * cbSectorSize) +
  387. cbSectorSize);
  388. sectDif = pdif->GetSect(cSectPerFat - 1);
  389. pvBase->Remove(pdif);
  390. }
  391. if (psect)
  392. {
  393. *psect = sectDif;
  394. }
  395. return pvBase->GetCFatSect((sectDif * cbSectorSize) +
  396. cbSectorSize);
  397. }
  398. //+---------------------------------------------------------------------------
  399. //
  400. // Function: GetFatSect
  401. //
  402. // Synopsis: Return a pointer to the appropriate sector in the fat
  403. //
  404. // Arguments: [pvBase] -- Pointer to base address of memory mapped file
  405. // [iFat] -- Index into fat desired
  406. // [cbSectorSize] -- Size in bytes of sector
  407. //
  408. // Returns: Pointer to appropriate sector
  409. //
  410. // History: 13-Feb-96 PhilipLa Created
  411. //
  412. //----------------------------------------------------------------------------
  413. CFatSect *GetFatSect(MAPFILE *pvBase,
  414. ULONG iFat,
  415. ULONG cbSectorSize,
  416. SECT *psect)
  417. {
  418. SECT sectFat;
  419. if (iFat < CSECTFAT)
  420. {
  421. //Fatsect can be found in header
  422. sectFat = pvBase->GetULONG(
  423. (ULONG) offsetof(CMSFHeaderData,_sectFat[iFat]));
  424. }
  425. else
  426. {
  427. ULONG cFatPerDif = (cbSectorSize / sizeof(SECT)) - 1;
  428. ULONG iDIF = (iFat - CSECTFAT) / cFatPerDif;
  429. USHORT oDIF = (USHORT)((iFat - CSECTFAT) % cFatPerDif);
  430. CFatSect *pDif = GetDIFSect(pvBase, iDIF, cbSectorSize, NULL);
  431. sectFat = pDif->GetSect(oDIF);
  432. pvBase->Remove(pDif);
  433. }
  434. CFatSect *pbFat = pvBase->GetCFatSect(
  435. (sectFat * cbSectorSize) + cbSectorSize);
  436. if (psect)
  437. {
  438. *psect = sectFat;
  439. }
  440. return (CFatSect *)pbFat;
  441. }
  442. //+---------------------------------------------------------------------------
  443. //
  444. // Function: GetNext
  445. //
  446. // Synopsis: Given a sector, return the next sector in the fat chain
  447. //
  448. // Arguments: [pvBase] -- Pointer to base address of memory mapped file
  449. // [sect] -- Sect desired
  450. // [cbSectorSize] -- Sector size in bytes
  451. //
  452. // Returns: Appropriate SECT value
  453. //
  454. // History: 13-Feb-96 PhilipLa Created
  455. //
  456. //----------------------------------------------------------------------------
  457. SECT GetNext(MAPFILE *pvBase,
  458. SECT sect,
  459. ULONG cbSectorSize)
  460. {
  461. SECT newsect;
  462. ULONG csectPerFat = cbSectorSize / sizeof(SECT);
  463. ULONG iFat = sect / csectPerFat;
  464. USHORT oFat = (USHORT)(sect % csectPerFat);
  465. CFatSect *pfs = GetFatSect(pvBase, iFat, cbSectorSize, NULL);
  466. newsect = pfs->GetSect(oFat);
  467. pvBase->Remove(pfs);
  468. return newsect;
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Function: ProcessControl, private
  473. //
  474. // Synopsis: Add control structures to processed script
  475. //
  476. // Arguments: [psProcessed] -- Pointer to processed script
  477. // [pvOld] -- Pointer to old file
  478. // [pcsectControl] -- Return location for total sectors processed
  479. //
  480. // Returns: Appropriate status code
  481. //
  482. // History: 05-Mar-96 PhilipLa Created
  483. //
  484. //----------------------------------------------------------------------------
  485. SCODE ProcessControl(SECT *psProcessed,
  486. MAPFILE *pvOld,
  487. ULONG *pcsectControl)
  488. {
  489. SECT sectCurrent = 0;
  490. CMSFHeaderData *phdr = (CMSFHeaderData *)pvOld->GetCMSFHeaderData();
  491. ULONG csectDif, csectFat;
  492. ULONG cbSectorSize;
  493. csectDif = phdr->_csectDif;
  494. csectFat = phdr->_csectFat;
  495. cbSectorSize = 1 << phdr->_uSectorShift;
  496. //We want the structures in the following order:
  497. //1) Enough fat and DIFat sectors to hold themselves and all of the
  498. // directory sectors.
  499. //2) All of the directory sectors
  500. //3) Everything else - the rest of the difat, the fat, and the minifat.
  501. //First find out how big the directory is
  502. SECT sectDir = phdr->_sectDirStart;
  503. ULONG csectDir = 0;
  504. while (sectDir != ENDOFCHAIN)
  505. {
  506. sectDir = GetNext(pvOld, sectDir, cbSectorSize);
  507. csectDir++;
  508. }
  509. //Now compute the number of fat sectors we need to hold the directory
  510. // plus the fat sectors themselves.
  511. ULONG csectFatNeeded = 0;
  512. ULONG csectDifNeeded = 0;
  513. ULONG csectNeededLast = 0;
  514. ULONG cfsSect = (cbSectorSize / sizeof(SECT));
  515. do
  516. {
  517. csectNeededLast = csectFatNeeded;
  518. csectFatNeeded = (csectFatNeeded + csectDifNeeded + csectDir +
  519. cfsSect - 1) /
  520. cfsSect;
  521. if (csectFatNeeded > CSECTFAT)
  522. {
  523. csectDifNeeded = (csectFatNeeded - CSECTFAT + cfsSect - 2) /
  524. (cfsSect - 1);
  525. }
  526. }
  527. while (csectFatNeeded != csectNeededLast);
  528. //Now we know how many DIF, Fat, and Directory sectors we need.
  529. //Lay those out first.
  530. //For those of you keeping score, the docfile will need to have exactly
  531. // csectFatNeeded + csectDifNeeded sectors downloaded before it can
  532. // be opened.
  533. for (ULONG i = 0; i < csectDifNeeded; i++)
  534. {
  535. SECT sectDif;
  536. pvOld->Remove(GetDIFSect(pvOld, i, cbSectorSize, &sectDif));
  537. psProcessed[sectDif] = sectCurrent++;
  538. }
  539. for (i = 0; i < csectFatNeeded; i++)
  540. {
  541. SECT sectFat;
  542. pvOld->Remove(GetFatSect(pvOld, i, cbSectorSize, &sectFat));
  543. psProcessed[sectFat] = sectCurrent++;
  544. }
  545. sectDir = phdr->_sectDirStart;
  546. for (i = 0; i < csectDir; i++)
  547. {
  548. layAssert(sectDir != ENDOFCHAIN);
  549. psProcessed[sectDir] = sectCurrent++;
  550. sectDir = GetNext(pvOld, sectDir, cbSectorSize);
  551. }
  552. //Now put down everything else
  553. for (i = csectDifNeeded; i < csectDif; i++)
  554. {
  555. SECT sectDif;
  556. GetDIFSect(pvOld, i, cbSectorSize, &sectDif);
  557. pvOld->Remove(GetDIFSect(pvOld, i, cbSectorSize, &sectDif));
  558. psProcessed[sectDif] = sectCurrent++;
  559. }
  560. for (i = csectFatNeeded; i < csectFat; i++)
  561. {
  562. SECT sectFat;
  563. pvOld->Remove(GetFatSect(pvOld, i, cbSectorSize, &sectFat));
  564. psProcessed[sectFat] = sectCurrent++;
  565. }
  566. //Finally minifat
  567. SECT sectMiniFat = phdr->_sectMiniFatStart;
  568. while (sectMiniFat != ENDOFCHAIN)
  569. {
  570. psProcessed[sectMiniFat] = sectCurrent++;
  571. sectMiniFat = GetNext(pvOld, sectMiniFat, cbSectorSize);
  572. }
  573. *pcsectControl = sectCurrent;
  574. pvOld->Remove(phdr);
  575. return S_OK;
  576. }
  577. //+---------------------------------------------------------------------------
  578. //
  579. // Function: ProcessScript
  580. //
  581. // Synopsis: Given a list of sectors in order, construct a mapping
  582. // of old sector->new sector
  583. //
  584. // Arguments: [psProcessed] -- Pointer to destination buffer
  585. // [psOriginal] -- Pointer to source script buffer
  586. // [csectFile] -- Count of sectors in file
  587. // [csectOriginal] -- Count of entries in original script
  588. // [sectRangeLocks] -- sector containing docfile range locks
  589. // [pcsectProcessed] -- Return location for number of entries
  590. // in processed script
  591. //
  592. // Returns: Appropriate status code
  593. //
  594. // History: 13-Feb-96 PhilipLa Created
  595. //
  596. //----------------------------------------------------------------------------
  597. SCODE ProcessScript(SECT *psProcessed,
  598. MAPFILE *psOriginal,
  599. ULONG csectFile,
  600. ULONG csectOriginal,
  601. ULONG csectControl,
  602. SECT sectRangeLocks,
  603. ULONG *pcsectProcessed)
  604. {
  605. SCODE sc = S_OK;
  606. #if DBG == 1
  607. ULONG csectProcessed = 0;
  608. #endif
  609. ULONG cDuplicates = 0;
  610. ULONG cUnlisted = 0;
  611. for (ULONG i = 0; i < csectOriginal; i++)
  612. {
  613. SECT sectOld = (*psOriginal)[i];
  614. if (sectOld >= csectFile)
  615. {
  616. //Weird. We're past the range of the file.
  617. return STG_E_UNKNOWN;
  618. }
  619. #if DBG == 1
  620. if (sectOld + 1> csectProcessed)
  621. {
  622. csectProcessed = sectOld + 1;
  623. }
  624. #endif
  625. if (psProcessed[sectOld] == ENDOFCHAIN)
  626. {
  627. psProcessed[sectOld] = i - cDuplicates + csectControl;
  628. }
  629. else
  630. {
  631. cDuplicates++;
  632. }
  633. }
  634. //Fill in holes
  635. for (i = 0; i < csectFile; i++)
  636. {
  637. if (psProcessed[i] == ENDOFCHAIN)
  638. {
  639. SECT sectNew = csectOriginal - cDuplicates + csectControl +
  640. cUnlisted;
  641. if (sectNew == sectRangeLocks) // skip over range locks
  642. {
  643. sectNew++;
  644. cUnlisted++;
  645. }
  646. psProcessed[i] = sectNew;
  647. cUnlisted++;
  648. #if DBG == 1
  649. if (sectNew + 1> csectProcessed)
  650. {
  651. csectProcessed = sectNew + 1;
  652. }
  653. #endif
  654. }
  655. #if DBG == 1
  656. //If we have control structures at the end of the file that are
  657. // not in the script anywhere (which may happen particularly often
  658. // on files produced with simple mode), we want to make sure to
  659. // update the count on those. For retail builds, we don't really
  660. // care about the count, so we can skip this.
  661. else if (psProcessed[i] + 1 > csectProcessed)
  662. {
  663. csectProcessed = psProcessed[i] + 1;
  664. }
  665. #endif
  666. }
  667. #if DBG == 1
  668. for (i = 0; i < csectProcessed; i++)
  669. {
  670. layDebugOut((DEB_IERROR, "Script[%lu] = %lx\n", i, psProcessed[i]));
  671. }
  672. #endif
  673. #if DBG == 1
  674. *pcsectProcessed = csectProcessed;
  675. #else
  676. *pcsectProcessed = csectFile;
  677. #endif
  678. return sc;
  679. }
  680. //+---------------------------------------------------------------------------
  681. //
  682. // Function: CopyData
  683. //
  684. // Synopsis: Given an old->new mapping, copy data from old mapping to
  685. // new mapping
  686. //
  687. // Arguments: [pvNew] -- Pointer to destination mapped file
  688. // [pvOld] -- Pointer to source mapped file
  689. // [psScript] -- Pointer to processed script
  690. // [csectFile] -- Count of sectors in the file
  691. // [cbSectorSize] -- Sector size in bytes
  692. //
  693. // Returns: Appropriate status code
  694. //
  695. // History: 13-Feb-96 PhilipLa Created
  696. //
  697. //----------------------------------------------------------------------------
  698. SCODE CopyData(MAPFILE *pvNew,
  699. MAPFILE *pvOld,
  700. SECT *psScript,
  701. ULONG csectFile,
  702. ULONG cbSectorSize)
  703. {
  704. SCODE sc = S_OK;
  705. #ifdef SUPPORT_FILE_MAPPING
  706. BYTE *pbSrc, *pbDest;
  707. pbSrc = (BYTE *)(pvOld->GetBaseAddress());
  708. pbDest = (BYTE *)(pvNew->GetBaseAddress());
  709. #endif
  710. for (ULONG i = 0; i < csectFile; i++)
  711. {
  712. #ifdef SUPPORT_FILE_MAPPING
  713. BYTE *pbSrcStart = (BYTE *)pbSrc + (i * cbSectorSize) +
  714. cbSectorSize;
  715. BYTE *pbDestStart = (BYTE *)pbDest + (psScript[i] * cbSectorSize) +
  716. cbSectorSize;
  717. if ((pbSrc != NULL) && pbDest != NULL)
  718. {
  719. CopyMemory(pbDestStart, pbSrcStart, cbSectorSize);
  720. }
  721. else
  722. #endif // SUPPORT_FILE_MAPPING
  723. {
  724. BYTE *pbBuffer = (BYTE *) CoTaskMemAlloc(cbSectorSize);
  725. if (!pbBuffer)
  726. {
  727. return STG_E_INSUFFICIENTMEMORY;
  728. }
  729. if (S_OK == (sc = pvOld->ReadFromFile(pbBuffer,
  730. (i * cbSectorSize) +
  731. cbSectorSize,
  732. cbSectorSize )))
  733. {
  734. sc = pvNew->WriteToFile(pbBuffer,
  735. (psScript[i] * cbSectorSize) +
  736. cbSectorSize,
  737. cbSectorSize );
  738. }
  739. CoTaskMemFree(pbBuffer);
  740. if (S_OK != sc)
  741. {
  742. return sc;
  743. }
  744. }
  745. }
  746. //Also the header.
  747. #ifdef SUPPORT_FILE_MAPPING
  748. if ((pbSrc != NULL) && (pbDest != NULL))
  749. {
  750. CopyMemory(pbDest, pbSrc, sizeof(CMSFHeaderData));
  751. }
  752. else
  753. #endif
  754. {
  755. BYTE *pbBuffer = (BYTE *) CoTaskMemAlloc(sizeof(CMSFHeaderData));
  756. if (!pbBuffer)
  757. {
  758. return STG_E_INSUFFICIENTMEMORY;
  759. }
  760. if (S_OK == (sc = pvOld->ReadFromFile( pbBuffer,
  761. 0,
  762. sizeof(CMSFHeaderData) )))
  763. {
  764. sc = pvNew->WriteToFile( pbBuffer,
  765. 0,
  766. sizeof(CMSFHeaderData) );
  767. }
  768. CoTaskMemFree(pbBuffer);
  769. if (S_OK != sc)
  770. {
  771. return sc;
  772. }
  773. }
  774. return S_OK;
  775. }
  776. //+---------------------------------------------------------------------------
  777. //
  778. // Function: RemapHeader
  779. //
  780. // Synopsis: Remap the docfile header using a processed script
  781. //
  782. // Arguments: [pvNew] -- Pointer to base of memory mapped file
  783. // [psScript] -- Pointer to processed script
  784. // [csectFile] -- Count of sectors in file
  785. //
  786. // Returns: Appropriate status code
  787. //
  788. // History: 13-Feb-96 PhilipLa Created
  789. //
  790. //----------------------------------------------------------------------------
  791. SCODE RemapHeader(MAPFILE *pvNew, SECT *psScript, ULONG csectFile)
  792. {
  793. SCODE sc = S_OK;
  794. CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
  795. //Directory start will never be EOC
  796. ph->_sectDirStart = psScript[ph->_sectDirStart];
  797. if (ph->_sectMiniFatStart != ENDOFCHAIN)
  798. ph->_sectMiniFatStart = psScript[ph->_sectMiniFatStart];
  799. if (ph->_sectDifStart != ENDOFCHAIN)
  800. ph->_sectDifStart = psScript[ph->_sectDifStart];
  801. for (ULONG i = 0; i < CSECTFAT; i++)
  802. {
  803. if (ph->_sectFat[i] != FREESECT)
  804. {
  805. ph->_sectFat[i] = psScript[ph->_sectFat[i]];
  806. }
  807. }
  808. sc = pvNew->WriteToFile(ph);
  809. pvNew->Remove(ph);
  810. return sc;
  811. }
  812. //+---------------------------------------------------------------------------
  813. //
  814. // Function: RemapDIF
  815. //
  816. // Synopsis: Remap the DIF according to a processed script
  817. //
  818. // Arguments: [pvNew] -- Pointer to base of memory mapped file
  819. // [psScript] -- Pointer to processed script
  820. // [csectFile] -- Count of sectors in file
  821. // [cbSectorSize] -- Sector size in bytes
  822. //
  823. // Returns: Appropriate status code
  824. //
  825. // History: 13-Feb-96 PhilipLa Created
  826. //
  827. //----------------------------------------------------------------------------
  828. SCODE RemapDIF(MAPFILE *pvNew,
  829. SECT *psScript,
  830. ULONG csectFile,
  831. ULONG cbSectorSize)
  832. {
  833. CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
  834. SCODE sc = S_OK;
  835. CFatSect *pfs = NULL;
  836. USHORT csectPerDif = (USHORT)(cbSectorSize / sizeof(SECT));
  837. SECT sectDif = ph->_sectDifStart;
  838. for (ULONG i = 0; i < ph->_csectDif; i++)
  839. {
  840. pfs = pvNew->GetCFatSect((sectDif * cbSectorSize) +
  841. cbSectorSize );
  842. for (USHORT j = 0; j < csectPerDif; j++)
  843. {
  844. SECT sectOld = pfs->GetSect(j);
  845. if ((sectOld != FREESECT) &&
  846. (sectOld != ENDOFCHAIN))
  847. {
  848. pfs->SetSect(j, psScript[sectOld]);
  849. }
  850. }
  851. sectDif = pfs->GetNextFat(csectPerDif - 1);
  852. sc = pvNew->WriteToFile(pfs);
  853. pvNew->Remove(pfs);
  854. }
  855. pvNew->Remove(ph);
  856. return sc;
  857. }
  858. //+---------------------------------------------------------------------------
  859. //
  860. // Function: RemapFat
  861. //
  862. // Synopsis: Remap the Fat according to a processed script and the original
  863. // file
  864. //
  865. // Arguments: [pvNew] -- Pointer to base of destination memory mapped file
  866. // [pvOld] -- Pointer to base of source memory mapped file
  867. // [psScript] -- Pointer to processed script
  868. // [csectFile] -- Count of sectors in file
  869. // [cbSectorSize] -- Sector size in bytes
  870. //
  871. // Returns: Appropriate status code
  872. //
  873. // History: 13-Feb-96 PhilipLa Created
  874. //
  875. // Notes: Since the processed script does not contain information
  876. // about individual fat chains, we need the old file in order
  877. // to construct the new fat.
  878. //
  879. //----------------------------------------------------------------------------
  880. SCODE RemapFat(MAPFILE *pvNew,
  881. MAPFILE *pvOld,
  882. SECT *psScript,
  883. ULONG csectFile,
  884. ULONG cbSectorSize)
  885. {
  886. CFatSect *pfsNew;
  887. CFatSect *pfsOld;
  888. SCODE sc = S_OK;
  889. ULONG csectFat = pvNew->GetULONG(
  890. (ULONG) offsetof(CMSFHeaderData, _csectFat));
  891. USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
  892. for (ULONG i = 0; i < csectFat; i++)
  893. {
  894. pfsNew = GetFatSect(pvNew, i, cbSectorSize, NULL);
  895. memset(pfsNew, 0xFF, cbSectorSize);
  896. sc = pvNew->WriteToFile(pfsNew);
  897. if (sc != S_OK)
  898. {
  899. return sc;
  900. }
  901. pvNew->Remove(pfsNew);
  902. }
  903. for (i = 0; i < csectFat; i++)
  904. {
  905. pfsOld = GetFatSect(pvOld, i, cbSectorSize, NULL);
  906. for (USHORT j = 0; j < csectPerFat; j++)
  907. {
  908. if (i * csectPerFat + j >= csectFile)
  909. {
  910. //Sector outside of current file size - no remapping
  911. //is necessary, and sector has already been marked
  912. //as free above.
  913. break;
  914. }
  915. SECT sectOld = pfsOld->GetSect(j);
  916. SECT sectNew = psScript[i * csectPerFat + j];
  917. ULONG iFatNew = sectNew / csectPerFat;
  918. USHORT oFatNew = (USHORT)(sectNew % csectPerFat);
  919. pfsNew = GetFatSect(pvNew, iFatNew, cbSectorSize, NULL);
  920. if (sectOld > MAXREGSECT)
  921. {
  922. pfsNew->SetSect(oFatNew, sectOld);
  923. }
  924. else
  925. {
  926. //Need to map contents.
  927. SECT sectMap = psScript[sectOld];
  928. pfsNew->SetSect(oFatNew, sectMap);
  929. }
  930. sc = pvNew->WriteToFile(pfsNew);
  931. pvNew->Remove(pfsNew);
  932. }
  933. pvOld->Remove(pfsOld);
  934. }
  935. return sc;
  936. }
  937. //+---------------------------------------------------------------------------
  938. //
  939. // Function: RemapDirectory
  940. //
  941. // Synopsis: Remap a directory based on a processed script
  942. //
  943. // Arguments: [pvNew] -- Pointer to base of memory mapped file
  944. // [psScript] -- Pointer to processed script
  945. // [csectFile] -- Count of sectors in file
  946. // [cbSectorSize] -- Sector size in bytes
  947. //
  948. // Returns: Appropriate status code
  949. //
  950. // History: 13-Feb-96 PhilipLa Created
  951. //
  952. //----------------------------------------------------------------------------
  953. SCODE RemapDirectory(MAPFILE *pvNew,
  954. SECT *psScript,
  955. ULONG csectFile,
  956. ULONG cbSectorSize)
  957. {
  958. CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
  959. SCODE sc = S_OK;
  960. USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
  961. USHORT cEntryPerSect = (USHORT)(cbSectorSize / sizeof(CDirEntry));
  962. SECT sectDir = ph->_sectDirStart;
  963. while (sectDir != ENDOFCHAIN)
  964. {
  965. CDirSect *pds = pvNew->GetCDirSect((sectDir * cbSectorSize) +
  966. cbSectorSize );
  967. for (USHORT i = 0; i < cEntryPerSect; i++)
  968. {
  969. CDirEntry *pde = pds->GetEntry(i);
  970. if (STREAMLIKE(pde->GetFlags()))
  971. {
  972. SECT sectOld = (ULONG) pde->GetStart();
  973. #ifdef LARGE_STREAMS
  974. ULONGLONG ulSize = pde->GetSize(cbSectorSize > 512);
  975. #else
  976. ULONG ulSize = pde->GetSize();
  977. #endif
  978. swap ((char *) &sectOld, sizeof(SECT));
  979. swap ((char *) &ulSize, sizeof(ulSize));
  980. if ((ulSize >= ph->_ulMiniSectorCutoff) ||
  981. (pde->GetFlags() == STGTY_ROOT))
  982. {
  983. if ((sectOld != ENDOFCHAIN) && (sectOld != FREESECT))
  984. {
  985. SECT sectNew = psScript[sectOld];
  986. swap ((char *) &sectNew, sizeof(SECT));
  987. pde->SetStart(sectNew);
  988. }
  989. }
  990. }
  991. }
  992. sectDir = GetNext(pvNew, sectDir, cbSectorSize);
  993. sc = pvNew->WriteToFile(pds);
  994. pvNew->Remove(pds);
  995. }
  996. pvNew->Remove(ph);
  997. return sc;
  998. }