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.

3556 lines
87 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. diskspac.c
  5. Abstract:
  6. APIs and supporting routines for disk space requirement
  7. calculation.
  8. Author:
  9. Ted Miller (tedm) 26-Jul-1996
  10. Revision History:
  11. Jamie Hunter (JamieHun) Apr-24-2002
  12. Security code review
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // An HDSKSPC actually points to one of these.
  18. //
  19. typedef struct _DISK_SPACE_LIST {
  20. MYLOCK Lock;
  21. PVOID DrivesTable;
  22. UINT Flags;
  23. } DISK_SPACE_LIST, *PDISK_SPACE_LIST;
  24. #define LockIt(h) BeginSynchronizedAccess(&h->Lock)
  25. #define UnlockIt(h) EndSynchronizedAccess(&h->Lock)
  26. __inline
  27. LONGLONG
  28. _AdjustSpace(
  29. IN LONGLONG sz,
  30. IN LONGLONG block
  31. )
  32. {
  33. //
  34. // 4097,512 should return 4097+(512-1) = 4608
  35. // -4097,512 should return -(4097+(512-1)) = -4608
  36. //
  37. LONGLONG sign = (sz<0?-1:1);
  38. LONGLONG rem = (sz*sign)%block;
  39. return sz + (rem ? sign*(block-rem) : 0);
  40. }
  41. //
  42. // These structures are stored as data associated with
  43. // paths/filenames in the string table.
  44. //
  45. typedef struct _XFILE {
  46. //
  47. // -1 means it doesn't currently exist
  48. //
  49. LONGLONG CurrentSize;
  50. //
  51. // -1 means it will be deleted.
  52. //
  53. LONGLONG NewSize;
  54. } XFILE, *PXFILE;
  55. typedef struct _XDIRECTORY {
  56. //
  57. // Value indicating how many bytes will be required
  58. // to hold all the files in the FilesTable after they
  59. // are put on a file queue and then the queue is committed.
  60. //
  61. // This may be a negative number indicating that space will
  62. // actually be freed!
  63. //
  64. LONGLONG SpaceRequired;
  65. PVOID FilesTable;
  66. } XDIRECTORY, *PXDIRECTORY;
  67. typedef struct _XDRIVE {
  68. //
  69. // Value indicating how many bytes will be required
  70. // to hold all the files in the space list for this drive.
  71. //
  72. // This may be a negative number indicating that space will
  73. // actually be freed!
  74. //
  75. LONGLONG SpaceRequired;
  76. PVOID DirsTable;
  77. DWORD BytesPerCluster;
  78. //
  79. // This is the amount to skew SpaceRequired, based on
  80. // SetupAdjustDiskSpaceList(). We track this separately
  81. // for flexibility.
  82. //
  83. LONGLONG Slop;
  84. } XDRIVE, *PXDRIVE;
  85. typedef struct _RETURN_BUFFER_INFO {
  86. PVOID ReturnBuffer;
  87. DWORD ReturnBufferSize;
  88. DWORD RequiredSize;
  89. BOOL IsUnicode;
  90. } RETURN_BUFFER_INFO, *PRETURN_BUFFER_INFO;
  91. BOOL
  92. pSetupQueryDrivesInDiskSpaceList(
  93. IN HDSKSPC DiskSpace,
  94. OUT PVOID ReturnBuffer, OPTIONAL
  95. IN DWORD ReturnBufferSize,
  96. OUT PDWORD RequiredSize, OPTIONAL
  97. IN BOOL IsUnicode
  98. );
  99. BOOL
  100. pAddOrRemoveFileFromSectionToDiskSpaceList(
  101. IN OUT PDISK_SPACE_LIST DiskSpaceList,
  102. IN HINF LayoutInf,
  103. IN PINFCONTEXT LineInSection, OPTIONAL
  104. IN PCTSTR FileName, OPTIONAL
  105. IN PCTSTR TargetDirectory,
  106. IN UINT Operation,
  107. IN BOOL Add,
  108. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  109. );
  110. BOOL
  111. _SetupAddSectionToDiskSpaceList(
  112. IN HDSKSPC DiskSpace,
  113. IN HINF InfHandle,
  114. IN HINF ListInfHandle, OPTIONAL
  115. IN PCTSTR SectionName,
  116. IN UINT Operation,
  117. IN PVOID Reserved1,
  118. IN UINT Reserved2,
  119. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  120. );
  121. BOOL
  122. _SetupRemoveSectionFromDiskSpaceList(
  123. IN HDSKSPC DiskSpace,
  124. IN HINF InfHandle,
  125. IN HINF ListInfHandle, OPTIONAL
  126. IN PCTSTR SectionName,
  127. IN UINT Operation,
  128. IN PVOID Reserved1,
  129. IN UINT Reserved2,
  130. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  131. );
  132. BOOL
  133. pAddOrRemoveInstallSection(
  134. IN HDSKSPC DiskSpace,
  135. IN HINF InfHandle,
  136. IN HINF LayoutInfHandle, OPTIONAL
  137. IN PCTSTR SectionName,
  138. IN BOOL Add,
  139. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  140. );
  141. BOOL
  142. pSetupAddToDiskSpaceList(
  143. IN PDISK_SPACE_LIST DiskSpaceList,
  144. IN PCTSTR TargetFilespec,
  145. IN LONGLONG FileSize,
  146. IN UINT Operation
  147. );
  148. BOOL
  149. pSetupRemoveFromDiskSpaceList(
  150. IN PDISK_SPACE_LIST DiskSpaceList,
  151. IN PCTSTR TargetFilespec,
  152. IN UINT Operation
  153. );
  154. VOID
  155. pRecalcSpace(
  156. IN OUT PDISK_SPACE_LIST DiskSpaceList,
  157. IN LONG DriveStringId
  158. );
  159. BOOL
  160. pStringTableCBEnumDrives(
  161. IN PVOID StringTable,
  162. IN LONG StringId,
  163. IN PCTSTR String,
  164. IN PVOID ExtraData,
  165. IN UINT ExtraDataSize,
  166. IN LPARAM lParam
  167. );
  168. BOOL
  169. pStringTableCBDelDrives(
  170. IN PVOID StringTable,
  171. IN LONG StringId,
  172. IN PCTSTR String,
  173. IN PVOID ExtraData,
  174. IN UINT ExtraDataSize,
  175. IN LPARAM lParam
  176. );
  177. BOOL
  178. pStringTableCBDelDirs(
  179. IN PVOID StringTable,
  180. IN LONG StringId,
  181. IN PCTSTR String,
  182. IN PVOID ExtraData,
  183. IN UINT ExtraDataSize,
  184. IN LPARAM lParam
  185. );
  186. BOOL
  187. pStringTableCBZeroDirsTableMember(
  188. IN PVOID StringTable,
  189. IN LONG StringId,
  190. IN PCTSTR String,
  191. IN PVOID ExtraData,
  192. IN UINT ExtraDataSize,
  193. IN LPARAM lParam
  194. );
  195. BOOL
  196. pStringTableCBDupMemberStringTable(
  197. IN PVOID StringTable,
  198. IN LONG StringId,
  199. IN PCTSTR String,
  200. IN PVOID ExtraData,
  201. IN UINT ExtraDataSize,
  202. IN LPARAM lParam
  203. );
  204. DWORD
  205. pParsePath(
  206. IN PCTSTR PathSpec,
  207. OUT PTSTR Buffer,
  208. OUT PTSTR *DirectoryPart,
  209. OUT PTSTR *FilePart,
  210. OUT LONGLONG *FileSize,
  211. IN UINT Flags
  212. );
  213. HDSKSPC
  214. SetupCreateDiskSpaceList(
  215. IN PVOID Reserved1,
  216. IN DWORD Reserved2,
  217. IN UINT Flags
  218. )
  219. /*++
  220. Routine Description:
  221. This routine creates a disk space list, which can be used to
  222. determine required disk space for a set of file operations
  223. that parallel those that an application will perform later,
  224. such as via the file queue APIs.
  225. Arguments:
  226. Reserved1 - Unused, must be 0.
  227. Reserved2 - Unused, must be 0.
  228. Flags - Specifies flags that govern operation of the disk space list.
  229. SPDSL_IGNORE_DISK: If this flag is set, then delete operations
  230. will be ignored, and copy operations will behave as if
  231. the target files are not present on the disk, regardless of
  232. whether the files are actually present. This flag is useful
  233. to determine an approximate size that can be associated with
  234. a set of files.
  235. SPDSL_DISALLOW_NEGATIVE_ADJUST:
  236. Return Value:
  237. Handle to disk space list to be used in subsequent operations,
  238. or NULL if the routine fails, in which case GetLastError()
  239. returns extended error info.
  240. --*/
  241. {
  242. PDISK_SPACE_LIST SpaceList = NULL;
  243. DWORD d;
  244. //
  245. // Validate args.
  246. //
  247. if(Reserved1 || Reserved2) {
  248. d = ERROR_INVALID_PARAMETER;
  249. goto c1;
  250. }
  251. //
  252. // validate what flags are allowed
  253. //
  254. if (Flags & ~(SPDSL_IGNORE_DISK|SPDSL_DISALLOW_NEGATIVE_ADJUST)) {
  255. d = ERROR_INVALID_PARAMETER;
  256. goto c1;
  257. }
  258. //
  259. // Allocate space for a structure.
  260. //
  261. SpaceList = MyMalloc(sizeof(DISK_SPACE_LIST));
  262. if(!SpaceList) {
  263. d = ERROR_NOT_ENOUGH_MEMORY;
  264. goto c1;
  265. }
  266. ZeroMemory(SpaceList,sizeof(DISK_SPACE_LIST));
  267. SpaceList->Flags = Flags;
  268. //
  269. // Create a string table for the drives.
  270. //
  271. SpaceList->DrivesTable = pStringTableInitialize(sizeof(XDRIVE));
  272. if(!SpaceList->DrivesTable) {
  273. d = ERROR_NOT_ENOUGH_MEMORY;
  274. goto c2;
  275. }
  276. //
  277. // Create a locking structure for this guy.
  278. //
  279. if(!InitializeSynchronizedAccess(&SpaceList->Lock)) {
  280. d = ERROR_NOT_ENOUGH_MEMORY;
  281. goto c3;
  282. }
  283. //
  284. // Success.
  285. //
  286. return(SpaceList);
  287. c3:
  288. pStringTableDestroy(SpaceList->DrivesTable);
  289. c2:
  290. if(SpaceList) {
  291. MyFree(SpaceList);
  292. }
  293. c1:
  294. SetLastError(d);
  295. return(NULL);
  296. }
  297. //
  298. // Ansi version.
  299. //
  300. HDSKSPC
  301. SetupCreateDiskSpaceListA(
  302. IN PVOID Reserved1,
  303. IN DWORD Reserved2,
  304. IN UINT Flags
  305. )
  306. {
  307. //
  308. // Nothing actually ansi/unicode specific now
  309. //
  310. return(SetupCreateDiskSpaceListW(Reserved1,Reserved2,Flags));
  311. }
  312. HDSKSPC
  313. SetupDuplicateDiskSpaceList(
  314. IN HDSKSPC DiskSpace,
  315. IN PVOID Reserved1,
  316. IN DWORD Reserved2,
  317. IN UINT Flags
  318. )
  319. /*++
  320. Routine Description:
  321. This routine duplicates a disk space, creating a new, fully independent
  322. disk space list.
  323. Arguments:
  324. DiskSpace - supplies handle of disk space list to be duplicated.
  325. Reserved1 - reserved, must be 0.
  326. Reserved2 - reserved, must be 0.
  327. Flags - reserved, must be 0.
  328. Return Value:
  329. If successful, returns a handle to a new disk space list.
  330. NULL if failure; GetLastError() returns extended error info.
  331. --*/
  332. {
  333. PDISK_SPACE_LIST OldSpaceList;
  334. PDISK_SPACE_LIST NewSpaceList = NULL; // shut up preFast
  335. DWORD d;
  336. BOOL b;
  337. XDRIVE xDrive;
  338. //
  339. // Validate args.
  340. //
  341. if(Reserved1 || Reserved2 || Flags) {
  342. d = ERROR_INVALID_PARAMETER;
  343. goto c0;
  344. }
  345. //
  346. // Allocate space for a new structure and create a locking structure.
  347. //
  348. NewSpaceList = MyMalloc(sizeof(DISK_SPACE_LIST));
  349. if(!NewSpaceList) {
  350. d = ERROR_NOT_ENOUGH_MEMORY;
  351. goto c0;
  352. }
  353. ZeroMemory(NewSpaceList,sizeof(DISK_SPACE_LIST));
  354. if(!InitializeSynchronizedAccess(&NewSpaceList->Lock)) {
  355. d = ERROR_NOT_ENOUGH_MEMORY;
  356. goto c1;
  357. }
  358. //
  359. // Lock down the existing space list.
  360. //
  361. OldSpaceList = DiskSpace;
  362. d = NO_ERROR;
  363. try {
  364. if(!LockIt(OldSpaceList)) {
  365. d = ERROR_INVALID_HANDLE;
  366. }
  367. } except(EXCEPTION_EXECUTE_HANDLER) {
  368. d = ERROR_INVALID_HANDLE;
  369. }
  370. if(d != NO_ERROR) {
  371. goto c2;
  372. }
  373. //
  374. // Duplicate the top-level string table. After we do this, we'll have
  375. // a string table whose items' extra data is XDRIVE structures,
  376. // which will each contain a string table handle for a string table for
  377. // directories. But we don't want to share that string table between
  378. // the old and new disk space tables. So start by zeroing the DirsTable
  379. // members of all the XDRIVE structures. This will let us clean up
  380. // more easily later in the error path.
  381. //
  382. MYASSERT(OldSpaceList->DrivesTable);
  383. NewSpaceList->DrivesTable = pStringTableDuplicate(OldSpaceList->DrivesTable);
  384. if(!NewSpaceList->DrivesTable) {
  385. d = ERROR_NOT_ENOUGH_MEMORY;
  386. goto c3;
  387. }
  388. pStringTableEnum(
  389. NewSpaceList->DrivesTable,
  390. &xDrive,
  391. sizeof(XDRIVE),
  392. pStringTableCBZeroDirsTableMember,
  393. 0
  394. );
  395. //
  396. // Now we enumerate the old drives table and duplicate each directory
  397. // string table into the new drives table. We take heavy advantage
  398. // of the fact that the ids are the same between the old and new tables.
  399. //
  400. b = pStringTableEnum(
  401. OldSpaceList->DrivesTable,
  402. &xDrive,
  403. sizeof(XDRIVE),
  404. pStringTableCBDupMemberStringTable,
  405. (LPARAM)NewSpaceList->DrivesTable
  406. );
  407. if(!b) {
  408. d = ERROR_NOT_ENOUGH_MEMORY;
  409. }
  410. if(d != NO_ERROR) {
  411. pStringTableEnum(
  412. NewSpaceList->DrivesTable,
  413. &xDrive,
  414. sizeof(XDRIVE),
  415. pStringTableCBDelDrives,
  416. 0
  417. );
  418. pStringTableDestroy(NewSpaceList->DrivesTable);
  419. }
  420. c3:
  421. //
  422. // Unlock the existing space list.
  423. //
  424. try {
  425. UnlockIt(OldSpaceList);
  426. } except(EXCEPTION_EXECUTE_HANDLER) {
  427. //
  428. // Don't worry if the pointer went bad, we're already done
  429. // with the important work.
  430. //
  431. ;
  432. }
  433. c2:
  434. if(d != NO_ERROR) {
  435. DestroySynchronizedAccess(&NewSpaceList->Lock);
  436. }
  437. c1:
  438. if(d != NO_ERROR) {
  439. MyFree(NewSpaceList);
  440. }
  441. c0:
  442. SetLastError(d);
  443. return((d == NO_ERROR) ? NewSpaceList : NULL);
  444. }
  445. //
  446. // Ansi version.
  447. //
  448. HDSKSPC
  449. SetupDuplicateDiskSpaceListA(
  450. IN HDSKSPC DiskSpace,
  451. IN PVOID Reserved1,
  452. IN DWORD Reserved2,
  453. IN UINT Flags
  454. )
  455. {
  456. //
  457. // Nothing actually ansi/unicode specific now
  458. //
  459. return(SetupDuplicateDiskSpaceListW(DiskSpace,Reserved1,Reserved2,Flags));
  460. }
  461. BOOL
  462. SetupDestroyDiskSpaceList(
  463. IN OUT HDSKSPC DiskSpace
  464. )
  465. /*++
  466. Routine Description:
  467. This routine destryos a disk space list which was created
  468. with SetupCreateDiskSpaceList() and releases all resources
  469. used thereby.
  470. Arguments:
  471. DiskSpace - supplies handle to space list to be deconstructed.
  472. Return Value:
  473. Boolean value indicating outcome. If FALSE, extended error info
  474. is available from GetLastError().
  475. --*/
  476. {
  477. PDISK_SPACE_LIST DiskSpaceList;
  478. DWORD rc;
  479. XDRIVE xDrive;
  480. DiskSpaceList = DiskSpace;
  481. rc = NO_ERROR;
  482. try {
  483. if(!LockIt(DiskSpaceList)) {
  484. rc = ERROR_INVALID_HANDLE;
  485. }
  486. } except(EXCEPTION_EXECUTE_HANDLER) {
  487. rc = ERROR_INVALID_HANDLE;
  488. }
  489. if(rc != NO_ERROR) {
  490. SetLastError(rc);
  491. return(FALSE);
  492. }
  493. try {
  494. DestroySynchronizedAccess(&DiskSpaceList->Lock);
  495. } except(EXCEPTION_EXECUTE_HANDLER) {
  496. //
  497. // Just swallow this.
  498. //
  499. ;
  500. }
  501. try {
  502. MYASSERT(DiskSpaceList->DrivesTable);
  503. //
  504. // Enumerate the drives string table. This in turn causes
  505. // all directory and file string tables to get destroyed.
  506. //
  507. pStringTableEnum(
  508. DiskSpaceList->DrivesTable,
  509. &xDrive,
  510. sizeof(XDRIVE),
  511. pStringTableCBDelDrives,
  512. 0
  513. );
  514. pStringTableDestroy(DiskSpaceList->DrivesTable);
  515. //
  516. // Free the disk space list guy.
  517. //
  518. MyFree(DiskSpaceList);
  519. } except(EXCEPTION_EXECUTE_HANDLER) {
  520. rc = ERROR_INVALID_HANDLE;
  521. }
  522. SetLastError(rc);
  523. return(rc == NO_ERROR);
  524. }
  525. BOOL
  526. SetupAdjustDiskSpaceList(
  527. IN HDSKSPC DiskSpace,
  528. IN LPCTSTR DriveRoot,
  529. IN LONGLONG Amount,
  530. IN PVOID Reserved1,
  531. IN UINT Reserved2
  532. )
  533. /*++
  534. Routine Description:
  535. This routine is used to add an absolute amount of required disk space
  536. for a drive.
  537. Arguments:
  538. DiskSpace - supplies a handle to a disk space list.
  539. DriveRoot - specifies a valid Win32 drive root. If this drive is not
  540. currently represented in the disk space list then an entry for it
  541. is added.
  542. Amount - supplies the amount of disk space by which to adjust space
  543. required on the drive. Use a negative number to remove space.
  544. Reserved1 - must be 0.
  545. Reserved2 - must be 0.
  546. Return Value:
  547. --*/
  548. {
  549. DWORD rc;
  550. BOOL b;
  551. if(Reserved1 || Reserved2) {
  552. SetLastError(ERROR_INVALID_PARAMETER);
  553. return(FALSE);
  554. }
  555. rc = NO_ERROR;
  556. try {
  557. if(!LockIt(((PDISK_SPACE_LIST)DiskSpace))) {
  558. rc = ERROR_INVALID_HANDLE;
  559. }
  560. } except(EXCEPTION_EXECUTE_HANDLER) {
  561. rc = ERROR_INVALID_HANDLE;
  562. }
  563. if(rc != NO_ERROR) {
  564. SetLastError(rc);
  565. return(FALSE);
  566. }
  567. //
  568. // pSetupAddToDiskSpaceList does all the work. That routine
  569. // uses SEH so no need for try/excepts here.
  570. //
  571. b = pSetupAddToDiskSpaceList(DiskSpace,DriveRoot,Amount,(UINT)(-1));
  572. rc = GetLastError();
  573. //
  574. // The try/except around the unlock simply prevents us from faulting
  575. // but we don't return error if the pointer goes bad.
  576. //
  577. try {
  578. UnlockIt(((PDISK_SPACE_LIST)DiskSpace));
  579. } except(EXCEPTION_EXECUTE_HANDLER) {
  580. ;
  581. }
  582. SetLastError(rc);
  583. return(b);
  584. }
  585. //
  586. // ANSI version
  587. //
  588. BOOL
  589. SetupAdjustDiskSpaceListA(
  590. IN HDSKSPC DiskSpace,
  591. IN LPCSTR DriveRoot,
  592. IN LONGLONG Amount,
  593. IN PVOID Reserved1,
  594. IN UINT Reserved2
  595. )
  596. {
  597. LPCWSTR p;
  598. BOOL b;
  599. DWORD rc;
  600. rc = pSetupCaptureAndConvertAnsiArg(DriveRoot,&p);
  601. if(rc != NO_ERROR) {
  602. SetLastError(rc);
  603. return(FALSE);
  604. }
  605. b = SetupAdjustDiskSpaceListW(DiskSpace,p,Amount,Reserved1,Reserved2);
  606. rc = GetLastError();
  607. MyFree(p);
  608. SetLastError(rc);
  609. return(b);
  610. }
  611. BOOL
  612. SetupAddToDiskSpaceList(
  613. IN HDSKSPC DiskSpace,
  614. IN PCTSTR TargetFilespec,
  615. IN LONGLONG FileSize,
  616. IN UINT Operation,
  617. IN PVOID Reserved1,
  618. IN UINT Reserved2
  619. )
  620. /*++
  621. Routine Description:
  622. This routine adds a single delete or copy operation to a
  623. disk space list.
  624. Note that disk compression is completely ignored by this routine.
  625. Files are assumed to occupy their full size on the disk.
  626. Arguments:
  627. DiskSpace - specifies handle to disk space list created by
  628. SetupCreateDiskSpaceList().
  629. TargetFilespec - specifies filename of the file to add
  630. to the disk space list. This will generally be a full win32
  631. path, though this is not a requirement. If it is not then
  632. standard win32 path semantics apply.
  633. FileSize - supplies the (uncompressed) size of the file as it will
  634. exist on the target when copied. Ignored for FILEOP_DELETE.
  635. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  636. Reserved1 - must be 0.
  637. Reserved2 - must be 0.
  638. Return Value:
  639. Boolean value indicating outcome. If FALSE, GetLastError() returns
  640. extended error information.
  641. --*/
  642. {
  643. DWORD rc;
  644. BOOL b;
  645. if(Reserved1 || Reserved2) {
  646. SetLastError(ERROR_INVALID_PARAMETER);
  647. return(FALSE);
  648. }
  649. rc = NO_ERROR;
  650. try {
  651. if(!LockIt(((PDISK_SPACE_LIST)DiskSpace))) {
  652. rc = ERROR_INVALID_HANDLE;
  653. }
  654. } except(EXCEPTION_EXECUTE_HANDLER) {
  655. rc = ERROR_INVALID_HANDLE;
  656. }
  657. if(rc != NO_ERROR) {
  658. SetLastError(rc);
  659. return(FALSE);
  660. }
  661. b = pSetupAddToDiskSpaceList(DiskSpace,TargetFilespec,FileSize,Operation);
  662. rc = GetLastError();
  663. //
  664. // The try/except around the unlock simply prevents us from faulting
  665. // but we don't return error if the pointer goes bad.
  666. //
  667. try {
  668. UnlockIt(((PDISK_SPACE_LIST)DiskSpace));
  669. } except(EXCEPTION_EXECUTE_HANDLER) {
  670. ;
  671. }
  672. SetLastError(rc);
  673. return(b);
  674. }
  675. //
  676. // ANSI version
  677. //
  678. BOOL
  679. SetupAddToDiskSpaceListA(
  680. IN HDSKSPC DiskSpace,
  681. IN PCSTR TargetFilespec,
  682. IN LONGLONG FileSize,
  683. IN UINT Operation,
  684. IN PVOID Reserved1,
  685. IN UINT Reserved2
  686. )
  687. {
  688. PWSTR targetFilespec;
  689. DWORD rc;
  690. BOOL b;
  691. rc = pSetupCaptureAndConvertAnsiArg(TargetFilespec,&targetFilespec);
  692. if(rc != NO_ERROR) {
  693. return(rc);
  694. }
  695. b = SetupAddToDiskSpaceListW(DiskSpace,targetFilespec,FileSize,Operation,Reserved1,Reserved2);
  696. rc = GetLastError();
  697. MyFree(targetFilespec);
  698. SetLastError(rc);
  699. return(b);
  700. }
  701. BOOL
  702. _SetupAddSectionToDiskSpaceList(
  703. IN HDSKSPC DiskSpace,
  704. IN HINF InfHandle,
  705. IN HINF ListInfHandle, OPTIONAL
  706. IN PCTSTR SectionName,
  707. IN UINT Operation,
  708. IN PVOID Reserved1,
  709. IN UINT Reserved2,
  710. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  711. )
  712. /*++
  713. Routine Description:
  714. This routine adds a delete or copy section to a disk space list.
  715. Note that disk compression is completely ignored by this routine.
  716. Files are assumed to occupy their full size on the disk.
  717. Arguments:
  718. DiskSpace - specifies handle to disk space list created by
  719. SetupCreateDiskSpaceList().
  720. InfHandle - supplies a handle to an open inf file, that contains the
  721. [SourceDisksFiles] section, and, if ListInfHandle is not specified,
  722. contains the section named by SectionName. This handle must be for
  723. a win95-style inf.
  724. ListInfHandle - if specified, supplies a handle to an open inf file
  725. containing the section to be added to the disk space list.
  726. Otherwise InfHandle is assumed to contain the section.
  727. SectionName - supplies the name of the section to be added to
  728. the disk space list.
  729. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  730. Reserved1 - must be 0.
  731. Reserved2 - must be 0.
  732. AltPlatformInfo - optionally, supplies alternate platform info to be used
  733. in determining the appropriately-decorated [SourceDisksFiles] section
  734. containing file size information.
  735. Return Value:
  736. Boolean value indicating outcome. If FALSE, GetLastError() returns
  737. extended error information.
  738. --*/
  739. {
  740. PDISK_SPACE_LIST DiskSpaceList;
  741. LONG LineCount;
  742. PCTSTR TargetFilename;
  743. BOOL b;
  744. INFCONTEXT LineContext;
  745. TCHAR FullTargetPath[MAX_PATH];
  746. DWORD FileSize;
  747. DWORD rc;
  748. //
  749. // Note throughout this routine that very little structured exception handling
  750. // is needed, since most of the work is performed by subroutines that are
  751. // properly guarded.
  752. //
  753. if(Reserved1 || Reserved2) {
  754. rc = ERROR_INVALID_PARAMETER;
  755. b = FALSE;
  756. goto c0;
  757. }
  758. //
  759. // Lock down the DiskSpace handle/structure.
  760. //
  761. DiskSpaceList = DiskSpace;
  762. rc = NO_ERROR;
  763. try {
  764. if(!LockIt(DiskSpaceList)) {
  765. rc = ERROR_INVALID_HANDLE;
  766. }
  767. } except(EXCEPTION_EXECUTE_HANDLER) {
  768. rc = ERROR_INVALID_HANDLE;
  769. }
  770. if(rc != NO_ERROR) {
  771. b = FALSE;
  772. goto c0;
  773. }
  774. if(!ListInfHandle) {
  775. ListInfHandle = InfHandle;
  776. }
  777. //
  778. // The section must at least exist; an empty section is
  779. // a trivial success case.
  780. //
  781. LineCount = SetupGetLineCount(ListInfHandle,SectionName);
  782. if(LineCount == -1) {
  783. rc = ERROR_SECTION_NOT_FOUND;
  784. b = FALSE;
  785. goto c1;
  786. }
  787. if(!LineCount) {
  788. b = TRUE;
  789. goto c1;
  790. }
  791. //
  792. // Find the first line. We know there is at least one since the line count
  793. // was checked above. Sanity check it anyway.
  794. //
  795. b = SetupFindFirstLine(ListInfHandle,SectionName,NULL,&LineContext);
  796. MYASSERT(b);
  797. if(!b) {
  798. rc = ERROR_SECTION_NOT_FOUND;
  799. goto c1;
  800. }
  801. //
  802. // Find the target path for this section.
  803. //
  804. if(!SetupGetTargetPath(NULL,&LineContext,NULL,FullTargetPath,MAX_PATH,NULL)) {
  805. rc = GetLastError();
  806. goto c1;
  807. }
  808. //
  809. // Process each line in the section.
  810. //
  811. do {
  812. b = pAddOrRemoveFileFromSectionToDiskSpaceList(
  813. DiskSpaceList,
  814. InfHandle,
  815. &LineContext,
  816. NULL,
  817. FullTargetPath,
  818. Operation,
  819. TRUE,
  820. AltPlatformInfo
  821. );
  822. if(!b) {
  823. rc = GetLastError();
  824. }
  825. } while(b && SetupFindNextLine(&LineContext,&LineContext));
  826. c1:
  827. try {
  828. UnlockIt(DiskSpaceList);
  829. } except(EXCEPTION_EXECUTE_HANDLER) {
  830. ;
  831. }
  832. c0:
  833. SetLastError(rc);
  834. return(b);
  835. }
  836. //
  837. // ANSI version
  838. //
  839. BOOL
  840. SetupAddSectionToDiskSpaceListA(
  841. IN HDSKSPC DiskSpace,
  842. IN HINF InfHandle,
  843. IN HINF ListInfHandle, OPTIONAL
  844. IN PCSTR SectionName,
  845. IN UINT Operation,
  846. IN PVOID Reserved1,
  847. IN UINT Reserved2
  848. )
  849. {
  850. PWSTR sectionName;
  851. BOOL b;
  852. DWORD rc;
  853. rc = pSetupCaptureAndConvertAnsiArg(SectionName,&sectionName);
  854. if(rc == NO_ERROR) {
  855. b = _SetupAddSectionToDiskSpaceList(
  856. DiskSpace,
  857. InfHandle,
  858. ListInfHandle,
  859. sectionName,
  860. Operation,
  861. Reserved1,
  862. Reserved2,
  863. NULL
  864. );
  865. rc = GetLastError();
  866. MyFree(sectionName);
  867. } else {
  868. b = FALSE;
  869. }
  870. SetLastError(rc);
  871. return(b);
  872. }
  873. BOOL
  874. SetupAddSectionToDiskSpaceList(
  875. IN HDSKSPC DiskSpace,
  876. IN HINF InfHandle,
  877. IN HINF ListInfHandle, OPTIONAL
  878. IN PCTSTR SectionName,
  879. IN UINT Operation,
  880. IN PVOID Reserved1,
  881. IN UINT Reserved2
  882. )
  883. {
  884. return _SetupAddSectionToDiskSpaceList(DiskSpace,
  885. InfHandle,
  886. ListInfHandle,
  887. SectionName,
  888. Operation,
  889. Reserved1,
  890. Reserved2,
  891. NULL
  892. );
  893. }
  894. BOOL
  895. SetupAddInstallSectionToDiskSpaceList(
  896. IN HDSKSPC DiskSpace,
  897. IN HINF InfHandle,
  898. IN HINF LayoutInfHandle, OPTIONAL
  899. IN PCTSTR SectionName,
  900. IN PVOID Reserved1,
  901. IN UINT Reserved2
  902. )
  903. /*++
  904. Routine Description:
  905. Processes an install section, looking for CopyFiles and DelFiles
  906. lines, and adds those sections to a disk space list.
  907. Arguments:
  908. Return Value:
  909. Win32 error code indicating outcome.
  910. --*/
  911. {
  912. if(Reserved1 || Reserved2) {
  913. SetLastError(ERROR_INVALID_PARAMETER);
  914. return(FALSE);
  915. }
  916. return(pAddOrRemoveInstallSection(DiskSpace,
  917. InfHandle,
  918. LayoutInfHandle,
  919. SectionName,
  920. TRUE,
  921. NULL
  922. ));
  923. }
  924. //
  925. // ANSI version
  926. //
  927. BOOL
  928. SetupAddInstallSectionToDiskSpaceListA(
  929. IN HDSKSPC DiskSpace,
  930. IN HINF InfHandle,
  931. IN HINF LayoutInfHandle, OPTIONAL
  932. IN PCSTR SectionName,
  933. IN PVOID Reserved1,
  934. IN UINT Reserved2
  935. )
  936. {
  937. PWSTR sectionName;
  938. DWORD rc;
  939. BOOL b;
  940. rc = pSetupCaptureAndConvertAnsiArg(SectionName,&sectionName);
  941. if(rc == NO_ERROR) {
  942. b = SetupAddInstallSectionToDiskSpaceListW(
  943. DiskSpace,
  944. InfHandle,
  945. LayoutInfHandle,
  946. sectionName,
  947. Reserved1,
  948. Reserved2
  949. );
  950. rc = GetLastError();
  951. MyFree(sectionName);
  952. } else {
  953. b = FALSE;
  954. }
  955. SetLastError(rc);
  956. return(b);
  957. }
  958. BOOL
  959. SetupRemoveFromDiskSpaceList(
  960. IN HDSKSPC DiskSpace,
  961. IN PCTSTR TargetFilespec,
  962. IN UINT Operation,
  963. IN PVOID Reserved1,
  964. IN UINT Reserved2
  965. )
  966. /*++
  967. Routine Description:
  968. This routine removes a single delete or copy operation from a
  969. disk space list.
  970. Arguments:
  971. DiskSpace - specifies handle to disk space list created by
  972. SetupCreateDiskSpaceList().
  973. TargetFilespec - specifies filename of the file to remove from
  974. the disk space list. This will generally be a full win32
  975. path, though this is not a requirement. If it is not then
  976. standard win32 path semantics apply.
  977. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  978. Reserved1 - must be 0.
  979. Reserved2 - must be 0.
  980. Return Value:
  981. If the file was not in the list, the routine returns TRUE and
  982. GetLastError() returns ERROR_INVALID_DRIVE or ERROR_INVALID_NAME.
  983. If the file was in the list then upon success the routine returns
  984. TRUE and GetLastError() returns NO_ERROR.
  985. If the routine fails for some other reason it returns FALSE and GetLastError()
  986. can be used to fetch extended error info.
  987. --*/
  988. {
  989. DWORD rc;
  990. BOOL b;
  991. if(Reserved1 || Reserved2) {
  992. SetLastError(ERROR_INVALID_PARAMETER);
  993. return(FALSE);
  994. }
  995. rc = NO_ERROR;
  996. try {
  997. if(!LockIt(((PDISK_SPACE_LIST)DiskSpace))) {
  998. rc = ERROR_INVALID_HANDLE;
  999. }
  1000. } except(EXCEPTION_EXECUTE_HANDLER) {
  1001. rc = ERROR_INVALID_HANDLE;
  1002. }
  1003. if(rc != NO_ERROR) {
  1004. SetLastError(rc);
  1005. return(FALSE);
  1006. }
  1007. b = pSetupRemoveFromDiskSpaceList(DiskSpace,TargetFilespec,Operation);
  1008. rc = GetLastError();
  1009. //
  1010. // The try/except around the unlock simply prevents us from faulting
  1011. // but we don't return error if the pointer goes bad.
  1012. //
  1013. try {
  1014. UnlockIt(((PDISK_SPACE_LIST)DiskSpace));
  1015. } except(EXCEPTION_EXECUTE_HANDLER) {
  1016. ;
  1017. }
  1018. SetLastError(rc);
  1019. return(b);
  1020. }
  1021. //
  1022. // ANSI version
  1023. //
  1024. BOOL
  1025. SetupRemoveFromDiskSpaceListA(
  1026. IN HDSKSPC DiskSpace,
  1027. IN PCSTR TargetFilespec,
  1028. IN UINT Operation,
  1029. IN PVOID Reserved1,
  1030. IN UINT Reserved2
  1031. )
  1032. {
  1033. PWSTR targetFilespec;
  1034. DWORD rc;
  1035. BOOL b;
  1036. rc = pSetupCaptureAndConvertAnsiArg(TargetFilespec,&targetFilespec);
  1037. if(rc != NO_ERROR) {
  1038. return(rc);
  1039. }
  1040. b = SetupRemoveFromDiskSpaceListW(DiskSpace,targetFilespec,Operation,Reserved1,Reserved2);
  1041. rc = GetLastError();
  1042. MyFree(targetFilespec);
  1043. SetLastError(rc);
  1044. return(b);
  1045. }
  1046. BOOL
  1047. _SetupRemoveSectionFromDiskSpaceList(
  1048. IN HDSKSPC DiskSpace,
  1049. IN HINF InfHandle,
  1050. IN HINF ListInfHandle, OPTIONAL
  1051. IN PCTSTR SectionName,
  1052. IN UINT Operation,
  1053. IN PVOID Reserved1,
  1054. IN UINT Reserved2,
  1055. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. This routine removes a delete or copy section from a disk space list.
  1060. The section is presumed to have been added via SetupAddSectionToDiskSpaceList,
  1061. though this is not a requirement. Files that have not actually been added
  1062. will not be removed.
  1063. Note that disk compression is completely ignored by this routine.
  1064. Files are assumed to occupy their full size on the disk.
  1065. Arguments:
  1066. DiskSpace - specifies handle to disk space list created by
  1067. SetupCreateDiskSpaceList().
  1068. InfHandle - supplies a handle to an open inf file, that contains the
  1069. [SourceDisksFiles] section, and, if ListInfHandle is not specified,
  1070. contains the section named by SectionName. This handle must be for
  1071. a win95-style inf.
  1072. ListInfHandle - if specified, supplies a handle to an open inf file
  1073. containing the section to be removed from the disk space list.
  1074. Otherwise InfHandle is assumed to contain the section.
  1075. SectionName - supplies the name of the section to be added to
  1076. the disk space list.
  1077. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  1078. Reserved1 - must be 0.
  1079. Reserved2 - must be 0.
  1080. AltPlatformInfo - optionally, supplies alternate platform info to be used
  1081. in determining the appropriately-decorated [SourceDisksFiles] section
  1082. containing file size information.
  1083. Return Value:
  1084. Boolean value indicating outcome. If FALSE, GetLastError() returns
  1085. extended error information.
  1086. --*/
  1087. {
  1088. PDISK_SPACE_LIST DiskSpaceList;
  1089. LONG LineCount;
  1090. PCTSTR TargetFilename;
  1091. BOOL b;
  1092. INFCONTEXT LineContext;
  1093. TCHAR FullTargetPath[MAX_PATH];
  1094. DWORD rc;
  1095. //
  1096. // Note throughout this routine that very little structured exception handling
  1097. // is needed, since most of the work is performed by subroutines that are
  1098. // properly guarded.
  1099. //
  1100. if(Reserved1 || Reserved2) {
  1101. rc = ERROR_INVALID_PARAMETER;
  1102. b = FALSE;
  1103. goto c0;
  1104. }
  1105. //
  1106. // Lock down the DiskSpace handle/structure.
  1107. //
  1108. DiskSpaceList = DiskSpace;
  1109. rc = NO_ERROR;
  1110. try {
  1111. if(!LockIt(DiskSpaceList)) {
  1112. rc = ERROR_INVALID_HANDLE;
  1113. }
  1114. } except(EXCEPTION_EXECUTE_HANDLER) {
  1115. rc = ERROR_INVALID_HANDLE;
  1116. }
  1117. if(rc != NO_ERROR) {
  1118. b = FALSE;
  1119. goto c0;
  1120. }
  1121. if(!ListInfHandle) {
  1122. ListInfHandle = InfHandle;
  1123. }
  1124. //
  1125. // The section must at least exist; an empty section is
  1126. // a trivial success case.
  1127. //
  1128. LineCount = SetupGetLineCount(ListInfHandle,SectionName);
  1129. if(LineCount == -1) {
  1130. rc = ERROR_SECTION_NOT_FOUND;
  1131. b = FALSE;
  1132. goto c1;
  1133. }
  1134. if(!LineCount) {
  1135. b = TRUE;
  1136. goto c1;
  1137. }
  1138. //
  1139. // Find the first line. We know there is at least one since the line count
  1140. // was checked above. Sanity check it anyway.
  1141. //
  1142. b = SetupFindFirstLine(ListInfHandle,SectionName,NULL,&LineContext);
  1143. MYASSERT(b);
  1144. if(!b) {
  1145. rc = ERROR_SECTION_NOT_FOUND;
  1146. b = FALSE;
  1147. goto c1;
  1148. }
  1149. //
  1150. // Find the target path for this section.
  1151. //
  1152. if(!SetupGetTargetPath(NULL,&LineContext,NULL,FullTargetPath,MAX_PATH,NULL)) {
  1153. rc = GetLastError();
  1154. b = FALSE;
  1155. goto c1;
  1156. }
  1157. //
  1158. // Process each line in the section.
  1159. //
  1160. do {
  1161. b = pAddOrRemoveFileFromSectionToDiskSpaceList(
  1162. DiskSpaceList,
  1163. InfHandle,
  1164. &LineContext,
  1165. NULL,
  1166. FullTargetPath,
  1167. Operation,
  1168. FALSE,
  1169. AltPlatformInfo
  1170. );
  1171. if(!b) {
  1172. rc = GetLastError();
  1173. }
  1174. } while(b && SetupFindNextLine(&LineContext,&LineContext));
  1175. c1:
  1176. try {
  1177. UnlockIt(DiskSpaceList);
  1178. } except(EXCEPTION_EXECUTE_HANDLER) {
  1179. ;
  1180. }
  1181. c0:
  1182. SetLastError(rc);
  1183. return(b);
  1184. }
  1185. //
  1186. // ANSI version
  1187. //
  1188. BOOL
  1189. SetupRemoveSectionFromDiskSpaceListA(
  1190. IN HDSKSPC DiskSpace,
  1191. IN HINF InfHandle,
  1192. IN HINF ListInfHandle, OPTIONAL
  1193. IN PCSTR SectionName,
  1194. IN UINT Operation,
  1195. IN PVOID Reserved1,
  1196. IN UINT Reserved2
  1197. )
  1198. {
  1199. PWSTR sectionName;
  1200. BOOL b;
  1201. DWORD rc;
  1202. rc = pSetupCaptureAndConvertAnsiArg(SectionName,&sectionName);
  1203. if(rc == NO_ERROR) {
  1204. b = _SetupRemoveSectionFromDiskSpaceList(
  1205. DiskSpace,
  1206. InfHandle,
  1207. ListInfHandle,
  1208. sectionName,
  1209. Operation,
  1210. Reserved1,
  1211. Reserved2,
  1212. NULL
  1213. );
  1214. rc = GetLastError();
  1215. MyFree(sectionName);
  1216. } else {
  1217. b = FALSE;
  1218. }
  1219. SetLastError(rc);
  1220. return(b);
  1221. }
  1222. BOOL
  1223. SetupRemoveSectionFromDiskSpaceList(
  1224. IN HDSKSPC DiskSpace,
  1225. IN HINF InfHandle,
  1226. IN HINF ListInfHandle, OPTIONAL
  1227. IN PCTSTR SectionName,
  1228. IN UINT Operation,
  1229. IN PVOID Reserved1,
  1230. IN UINT Reserved2
  1231. )
  1232. {
  1233. return _SetupRemoveSectionFromDiskSpaceList(DiskSpace,
  1234. InfHandle,
  1235. ListInfHandle,
  1236. SectionName,
  1237. Operation,
  1238. Reserved1,
  1239. Reserved2,
  1240. NULL
  1241. );
  1242. }
  1243. BOOL
  1244. SetupRemoveInstallSectionFromDiskSpaceList(
  1245. IN HDSKSPC DiskSpace,
  1246. IN HINF InfHandle,
  1247. IN HINF LayoutInfHandle, OPTIONAL
  1248. IN PCTSTR SectionName,
  1249. IN PVOID Reserved1,
  1250. IN UINT Reserved2
  1251. )
  1252. /*++
  1253. Routine Description:
  1254. Processes an install section, looking for CopyFiles and DelFiles
  1255. lines, and removes those sections from a disk space list.
  1256. Arguments:
  1257. DiskSpace - supplies a handle to a disk space list.
  1258. InfHandle - supplies a handle to an open inf file, that contains the
  1259. [SourceDisksFiles] section, and, if ListInfHandle is not specified,
  1260. contains the section named by SectionName. This handle must be for
  1261. a win95-style inf.
  1262. ListInfHandle - if specified, supplies a handle to an open inf file
  1263. containing the section to be removed from the disk space list.
  1264. Otherwise InfHandle is assumed to contain the section.
  1265. SectionName - supplies the name of the section to be added to
  1266. the disk space list.
  1267. Reserved1 - must be 0.
  1268. Reserved2 - must be 0.
  1269. Return Value:
  1270. Boolean value indicating outcome. If FALSE, extended error info
  1271. is available via GetLastError().
  1272. --*/
  1273. {
  1274. if(Reserved1 || Reserved2) {
  1275. SetLastError(ERROR_INVALID_PARAMETER);
  1276. return(FALSE);
  1277. }
  1278. return(pAddOrRemoveInstallSection(DiskSpace,
  1279. InfHandle,
  1280. LayoutInfHandle,
  1281. SectionName,
  1282. FALSE,
  1283. NULL
  1284. ));
  1285. }
  1286. //
  1287. // ANSI version
  1288. //
  1289. BOOL
  1290. SetupRemoveInstallSectionFromDiskSpaceListA(
  1291. IN HDSKSPC DiskSpace,
  1292. IN HINF InfHandle,
  1293. IN HINF LayoutInfHandle, OPTIONAL
  1294. IN PCSTR SectionName,
  1295. IN PVOID Reserved1,
  1296. IN UINT Reserved2
  1297. )
  1298. {
  1299. PWSTR sectionName;
  1300. DWORD rc;
  1301. BOOL b;
  1302. rc = pSetupCaptureAndConvertAnsiArg(SectionName,&sectionName);
  1303. if(rc == NO_ERROR) {
  1304. b = SetupRemoveInstallSectionFromDiskSpaceListW(
  1305. DiskSpace,
  1306. InfHandle,
  1307. LayoutInfHandle,
  1308. sectionName,
  1309. Reserved1,
  1310. Reserved2
  1311. );
  1312. rc = GetLastError();
  1313. MyFree(sectionName);
  1314. } else {
  1315. b = FALSE;
  1316. }
  1317. SetLastError(rc);
  1318. return(b);
  1319. }
  1320. BOOL
  1321. SetupQuerySpaceRequiredOnDrive(
  1322. IN HDSKSPC DiskSpace,
  1323. IN PCTSTR DriveSpec,
  1324. OUT LONGLONG *SpaceRequired,
  1325. IN PVOID Reserved1,
  1326. IN UINT Reserved2
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. Examine a disk space list to determine the space required on a
  1331. particular drive.
  1332. Arguments:
  1333. DiskSpace - supplies a handle to a disk space list.
  1334. DriveSpec - specifies the drive for which space info is desired.
  1335. This should be in the form x: or \\server\share.
  1336. SpaceRequired - if the function succeeds, receives the amount
  1337. of space required. This may be 0 or a negative number!
  1338. Reserved1 - reserved, must be 0.
  1339. Reserved2 - reserved, must be 0.
  1340. Return Value:
  1341. Boolean value indicating outcome. If TRUE, SpaceRequired is filled in.
  1342. If FALSE, extended error info is available via GetLastError():
  1343. ERROR_INVALID_HANDLE - the specified DiskSpace handle is invalid.
  1344. ERROR_INVALID_DRIVE - the given drive is not in the disk space list.
  1345. --*/
  1346. {
  1347. PDISK_SPACE_LIST DiskSpaceList;
  1348. DWORD rc;
  1349. BOOL b;
  1350. LONG l;
  1351. DWORD Hash;
  1352. DWORD StringLength;
  1353. XDRIVE xDrive;
  1354. TCHAR drive[MAX_PATH];
  1355. if(Reserved1 || Reserved2) {
  1356. SetLastError(ERROR_INVALID_PARAMETER);
  1357. return(FALSE);
  1358. }
  1359. //
  1360. // Lock down the DiskSpace handle/structure.
  1361. //
  1362. DiskSpaceList = DiskSpace;
  1363. rc = NO_ERROR;
  1364. try {
  1365. if(!LockIt(DiskSpaceList)) {
  1366. rc = ERROR_INVALID_HANDLE;
  1367. }
  1368. } except(EXCEPTION_EXECUTE_HANDLER) {
  1369. rc = ERROR_INVALID_HANDLE;
  1370. }
  1371. if(rc != NO_ERROR) {
  1372. SetLastError(rc);
  1373. return(FALSE);
  1374. }
  1375. try {
  1376. lstrcpyn(drive,DriveSpec,MAX_PATH);
  1377. MYASSERT(DiskSpaceList->DrivesTable);
  1378. l = pStringTableLookUpString(
  1379. DiskSpaceList->DrivesTable,
  1380. drive,
  1381. &StringLength,
  1382. &Hash,
  1383. NULL,
  1384. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  1385. NULL,
  1386. 0
  1387. );
  1388. if(l != -1) {
  1389. //
  1390. // Found the drive. Recalc space and return it.
  1391. //
  1392. pRecalcSpace(DiskSpaceList,l);
  1393. pStringTableGetExtraData(DiskSpaceList->DrivesTable,l,&xDrive,sizeof(XDRIVE));
  1394. *SpaceRequired = xDrive.SpaceRequired + xDrive.Slop;
  1395. b = TRUE;
  1396. } else {
  1397. rc = ERROR_INVALID_DRIVE;
  1398. b = FALSE;
  1399. }
  1400. } except(EXCEPTION_EXECUTE_HANDLER) {
  1401. rc = ERROR_INVALID_PARAMETER;
  1402. b = FALSE;
  1403. }
  1404. try {
  1405. UnlockIt(DiskSpaceList);
  1406. } except(EXCEPTION_EXECUTE_HANDLER) {
  1407. ;
  1408. }
  1409. SetLastError(rc);
  1410. return(b);
  1411. }
  1412. #ifdef UNICODE
  1413. //
  1414. // ANSI version
  1415. //
  1416. BOOL
  1417. SetupQuerySpaceRequiredOnDriveA(
  1418. IN HDSKSPC DiskSpace,
  1419. IN PCSTR DriveSpec,
  1420. OUT LONGLONG *SpaceRequired,
  1421. IN PVOID Reserved1,
  1422. IN UINT Reserved2
  1423. )
  1424. {
  1425. PCWSTR drivespec;
  1426. DWORD rc;
  1427. BOOL b;
  1428. rc = pSetupCaptureAndConvertAnsiArg(DriveSpec,&drivespec);
  1429. if(rc == NO_ERROR) {
  1430. b = SetupQuerySpaceRequiredOnDrive(DiskSpace,drivespec,SpaceRequired,Reserved1,Reserved2);
  1431. rc = GetLastError();
  1432. MyFree(drivespec);
  1433. } else {
  1434. b = FALSE;
  1435. }
  1436. SetLastError(rc);
  1437. return(b);
  1438. }
  1439. #else
  1440. //
  1441. // Unicode stub
  1442. //
  1443. BOOL
  1444. SetupQuerySpaceRequiredOnDriveW(
  1445. IN HDSKSPC DiskSpace,
  1446. IN PCWSTR DriveSpec,
  1447. OUT LONGLONG *SpaceRequired,
  1448. IN PVOID Reserved1,
  1449. IN UINT Reserved2
  1450. )
  1451. {
  1452. UNREFERENCED_PARAMETER(DiskSpace);
  1453. UNREFERENCED_PARAMETER(DriveSpec);
  1454. UNREFERENCED_PARAMETER(SpaceRequired);
  1455. UNREFERENCED_PARAMETER(Reserved1);
  1456. UNREFERENCED_PARAMETER(Reserved2);
  1457. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1458. return(FALSE);
  1459. }
  1460. #endif
  1461. BOOL
  1462. SetupQueryDrivesInDiskSpaceListA(
  1463. IN HDSKSPC DiskSpace,
  1464. OUT PSTR ReturnBuffer, OPTIONAL
  1465. IN DWORD ReturnBufferSize,
  1466. OUT PDWORD RequiredSize OPTIONAL
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. This routine fills a caller-supplied buffer with drive specs for each
  1471. drive currently represented in the given disk space list.
  1472. Arguments:
  1473. DiskSpace - supplies a disk space list handle.
  1474. ReturnBuffer - if supplied, points to a buffer that gets packed with
  1475. the drive specs, followed by a final terminating nul. If not specified
  1476. and not other error occurs, the function succeeds and fills in
  1477. RequiredSize.
  1478. ReturnBufferSize - supplies the size (chars for Unicode, bytes for ANSI)
  1479. of the buffer pointed by ReturnBuffer. Ingored if ReturnBuffer
  1480. is not specified.
  1481. RequiredSize - if specified, receives the size of the buffer required
  1482. to hold the list of drives and terminating nul.
  1483. Return Value:
  1484. Boolean value indicating outcome. If the function returns FALSE,
  1485. extended error info is available via GetLastError(). If GetLastError()
  1486. returns ERROR_INSUFFICIENT_BUFFER then ReturnBuffer was specified but
  1487. ReturnBufferSize indicated that the supplied buffer was too small.
  1488. --*/
  1489. {
  1490. BOOL b;
  1491. b = pSetupQueryDrivesInDiskSpaceList(
  1492. DiskSpace,
  1493. ReturnBuffer,
  1494. ReturnBufferSize,
  1495. RequiredSize
  1496. #ifdef UNICODE
  1497. ,FALSE
  1498. #endif
  1499. );
  1500. return(b);
  1501. }
  1502. BOOL
  1503. SetupQueryDrivesInDiskSpaceListW(
  1504. IN HDSKSPC DiskSpace,
  1505. OUT PWSTR ReturnBuffer, OPTIONAL
  1506. IN DWORD ReturnBufferSize,
  1507. OUT PDWORD RequiredSize OPTIONAL
  1508. )
  1509. /*++
  1510. Routine Description:
  1511. See SetupQueryDrivesInDiskSpaceListA.
  1512. Arguments:
  1513. See SetupQueryDrivesInDiskSpaceListA.
  1514. Return Value:
  1515. See SetupQueryDrivesInDiskSpaceListA.
  1516. --*/
  1517. {
  1518. BOOL b;
  1519. #ifdef UNICODE
  1520. b = pSetupQueryDrivesInDiskSpaceList(
  1521. DiskSpace,
  1522. ReturnBuffer,
  1523. ReturnBufferSize,
  1524. RequiredSize,
  1525. TRUE
  1526. );
  1527. #else
  1528. UNREFERENCED_PARAMETER(DiskSpace);
  1529. UNREFERENCED_PARAMETER(ReturnBuffer);
  1530. UNREFERENCED_PARAMETER(ReturnBufferSize);
  1531. UNREFERENCED_PARAMETER(RequiredSize);
  1532. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1533. b = FALSE;
  1534. #endif
  1535. return(b);
  1536. }
  1537. BOOL
  1538. pSetupQueryDrivesInDiskSpaceList(
  1539. IN HDSKSPC DiskSpace,
  1540. OUT PVOID ReturnBuffer, OPTIONAL
  1541. IN DWORD ReturnBufferSize,
  1542. OUT PDWORD RequiredSize OPTIONAL
  1543. #ifdef UNICODE
  1544. IN ,BOOL IsUnicode
  1545. #endif
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. Worker routine for SetupQueryDrivesInDiskSpaceList.
  1550. Arguments:
  1551. Same as SetupQueryDrivesInDiskSpaceListA/W.
  1552. IsUnicode - for Unicode DLL, specifies whether buffer args
  1553. are ansi or unicode.
  1554. Return Value:
  1555. Same as SetupQueryDrivesInDiskSpaceListA/W.
  1556. --*/
  1557. {
  1558. PDISK_SPACE_LIST DiskSpaceList;
  1559. DWORD rc;
  1560. BOOL b;
  1561. XDRIVE xDrive;
  1562. RETURN_BUFFER_INFO ReturnBufferInfo;
  1563. //
  1564. // Lock down the DiskSpace handle/structure.
  1565. //
  1566. DiskSpaceList = DiskSpace;
  1567. rc = NO_ERROR;
  1568. try {
  1569. if(!LockIt(DiskSpaceList)) {
  1570. rc = ERROR_INVALID_HANDLE;
  1571. }
  1572. } except(EXCEPTION_EXECUTE_HANDLER) {
  1573. rc = ERROR_INVALID_HANDLE;
  1574. }
  1575. if(rc != NO_ERROR) {
  1576. SetLastError(rc);
  1577. return(FALSE);
  1578. }
  1579. try {
  1580. ReturnBufferInfo.ReturnBuffer = ReturnBuffer;
  1581. ReturnBufferInfo.ReturnBufferSize = ReturnBufferSize;
  1582. ReturnBufferInfo.RequiredSize = 0;
  1583. #ifdef UNICODE
  1584. ReturnBufferInfo.IsUnicode = IsUnicode;
  1585. #endif
  1586. MYASSERT(DiskSpaceList->DrivesTable);
  1587. b = pStringTableEnum(
  1588. DiskSpaceList->DrivesTable,
  1589. &xDrive,
  1590. sizeof(XDRIVE),
  1591. pStringTableCBEnumDrives,
  1592. (LPARAM)&ReturnBufferInfo
  1593. );
  1594. if(b) {
  1595. //
  1596. // Need one more char slot for the extra terminating nul.
  1597. //
  1598. ReturnBufferInfo.RequiredSize++;
  1599. if(RequiredSize) {
  1600. *RequiredSize = ReturnBufferInfo.RequiredSize;
  1601. }
  1602. if(ReturnBuffer) {
  1603. if(ReturnBufferInfo.RequiredSize <= ReturnBufferSize) {
  1604. #ifdef UNICODE
  1605. if(!IsUnicode) {
  1606. ((PSTR)ReturnBuffer)[ReturnBufferInfo.RequiredSize-1] = 0;
  1607. } else
  1608. #endif
  1609. ((PTSTR)ReturnBuffer)[ReturnBufferInfo.RequiredSize-1] = 0;
  1610. } else {
  1611. rc = ERROR_INSUFFICIENT_BUFFER;
  1612. b = FALSE;
  1613. }
  1614. }
  1615. } else {
  1616. rc = ERROR_INSUFFICIENT_BUFFER;
  1617. }
  1618. } except(EXCEPTION_EXECUTE_HANDLER) {
  1619. rc = ERROR_INVALID_PARAMETER;
  1620. b = FALSE;
  1621. }
  1622. try {
  1623. UnlockIt(DiskSpaceList);
  1624. } except(EXCEPTION_EXECUTE_HANDLER) {
  1625. ;
  1626. }
  1627. SetLastError(rc);
  1628. return(b);
  1629. }
  1630. BOOL
  1631. pAddOrRemoveInstallSection(
  1632. IN HDSKSPC DiskSpace,
  1633. IN HINF InfHandle,
  1634. IN HINF LayoutInfHandle, OPTIONAL
  1635. IN PCTSTR SectionName,
  1636. IN BOOL Add,
  1637. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  1638. )
  1639. /*++
  1640. Routine Description:
  1641. Arguments:
  1642. Return Value:
  1643. --*/
  1644. {
  1645. DWORD rc;
  1646. BOOL b;
  1647. unsigned i;
  1648. unsigned numops;
  1649. UINT operation;
  1650. PDISK_SPACE_LIST DiskSpaceList;
  1651. INFCONTEXT LineContext;
  1652. DWORD FieldCount;
  1653. DWORD Field;
  1654. PCTSTR SectionSpec;
  1655. PCTSTR Operations[1] = { TEXT("Copyfiles") };
  1656. INFCONTEXT SectionLineContext;
  1657. TCHAR DefaultTarget[MAX_PATH];
  1658. //
  1659. // Delfiles causes too many issues
  1660. // removed to give a good "worst case" scenario
  1661. // however we intend to add it back along with
  1662. // RenFiles When this issue is revisited, change numops
  1663. // The Operations array and the switch to convert i to operation
  1664. //
  1665. // PCTSTR Operations[2] = { TEXT("Delfiles"),TEXT("Copyfiles") };
  1666. //
  1667. //
  1668. // Lock down the DiskSpace handle/structure.
  1669. //
  1670. DiskSpaceList = DiskSpace;
  1671. rc = NO_ERROR;
  1672. b = TRUE;
  1673. DefaultTarget[0] = 0;
  1674. //
  1675. // only handle Copyfiles at the moment
  1676. //
  1677. numops = 1;
  1678. try {
  1679. if(!LockIt(DiskSpaceList)) {
  1680. rc = ERROR_INVALID_HANDLE;
  1681. }
  1682. } except(EXCEPTION_EXECUTE_HANDLER) {
  1683. rc = ERROR_INVALID_HANDLE;
  1684. }
  1685. if(rc != NO_ERROR) {
  1686. b = FALSE;
  1687. goto c0;
  1688. }
  1689. if(!LayoutInfHandle) {
  1690. LayoutInfHandle = InfHandle;
  1691. }
  1692. //
  1693. // see if install section exists for diagnostics (this will also check InfHandle)
  1694. // however proceed so that we don't break existing broken code :-(
  1695. //
  1696. if (!SetupFindFirstLine(InfHandle,SectionName,NULL,&LineContext)) {
  1697. DWORD x;
  1698. x = GetLastError();
  1699. pSetupLogSectionError(InfHandle,NULL,NULL,NULL,SectionName,MSG_LOG_NOSECTION_SPACE,x,NULL);
  1700. }
  1701. b = TRUE;
  1702. for(i=0; b && (i < numops); i++) {
  1703. //
  1704. // Find the relevent line in the given install section.
  1705. // If not present then we're done with this operation.
  1706. //
  1707. if(!SetupFindFirstLine(InfHandle,SectionName,Operations[i],&LineContext)) {
  1708. continue;
  1709. }
  1710. switch(i) {
  1711. case 0:
  1712. operation = FILEOP_COPY;
  1713. break;
  1714. default:
  1715. //
  1716. // if we get here, someone changed numops
  1717. // without changing this switch
  1718. //
  1719. MYASSERT(FALSE);
  1720. break;
  1721. }
  1722. do {
  1723. //
  1724. // Each value on the line in the given install section
  1725. // is the name of another section.
  1726. //
  1727. FieldCount = SetupGetFieldCount(&LineContext);
  1728. for(Field=1; b && (Field<=FieldCount); Field++) {
  1729. if(SectionSpec = pSetupGetField(&LineContext,Field)) {
  1730. //
  1731. // Handle single-file copy specially.
  1732. //
  1733. if((operation == FILEOP_COPY) && (*SectionSpec == TEXT('@'))) {
  1734. if(!DefaultTarget[0]) {
  1735. //
  1736. // Fetch the default target path for this inf, for use with
  1737. // single-file copy specs.
  1738. //
  1739. b = SetupGetTargetPath(
  1740. InfHandle,
  1741. NULL,
  1742. NULL,
  1743. DefaultTarget,
  1744. MAX_PATH,
  1745. NULL
  1746. );
  1747. }
  1748. if(b) {
  1749. b = pAddOrRemoveFileFromSectionToDiskSpaceList(
  1750. DiskSpace,
  1751. LayoutInfHandle,
  1752. NULL,
  1753. SectionSpec+1,
  1754. DefaultTarget,
  1755. operation,
  1756. Add,
  1757. AltPlatformInfo
  1758. );
  1759. }
  1760. if(!b) {
  1761. rc = GetLastError();
  1762. }
  1763. } else if(SetupGetLineCount(InfHandle,SectionSpec) > 0) {
  1764. //
  1765. // The section exists and is not empty.
  1766. // Add/remove it to the space list.
  1767. //
  1768. if(Add) {
  1769. b = _SetupAddSectionToDiskSpaceList(
  1770. DiskSpace,
  1771. LayoutInfHandle,
  1772. InfHandle,
  1773. SectionSpec,
  1774. operation,
  1775. 0,0,
  1776. AltPlatformInfo
  1777. );
  1778. } else {
  1779. b = _SetupRemoveSectionFromDiskSpaceList(
  1780. DiskSpace,
  1781. LayoutInfHandle,
  1782. InfHandle,
  1783. SectionSpec,
  1784. operation,
  1785. 0,0,
  1786. AltPlatformInfo
  1787. );
  1788. }
  1789. if(!b) {
  1790. rc = GetLastError();
  1791. }
  1792. }
  1793. }
  1794. }
  1795. } while(b && SetupFindNextMatchLine(&LineContext,Operations[i],&LineContext));
  1796. }
  1797. try {
  1798. UnlockIt(DiskSpaceList);
  1799. } except(EXCEPTION_EXECUTE_HANDLER) {
  1800. ;
  1801. }
  1802. c0:
  1803. SetLastError(rc);
  1804. return(b);
  1805. }
  1806. BOOL
  1807. pAddOrRemoveFileFromSectionToDiskSpaceList(
  1808. IN OUT PDISK_SPACE_LIST DiskSpaceList,
  1809. IN HINF LayoutInf,
  1810. IN PINFCONTEXT LineInSection, OPTIONAL
  1811. IN PCTSTR FileName, OPTIONAL
  1812. IN PCTSTR TargetDirectory,
  1813. IN UINT Operation,
  1814. IN BOOL Add,
  1815. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo OPTIONAL
  1816. )
  1817. {
  1818. PCTSTR TargetFilename;
  1819. TCHAR FullTargetPath[MAX_PATH];
  1820. DWORD FileSize;
  1821. BOOL b;
  1822. DWORD rc;
  1823. //
  1824. // Get the target filename out of the line.
  1825. // Field 1 is the target so there must be one for the line to be valid.
  1826. //
  1827. if(TargetFilename = LineInSection ? pSetupFilenameFromLine(LineInSection,FALSE) : FileName) {
  1828. //
  1829. // Form the full target path by concatenating the target dir
  1830. // for this section and the target filename.
  1831. //
  1832. lstrcpyn(FullTargetPath,TargetDirectory,MAX_PATH);
  1833. pSetupConcatenatePaths(FullTargetPath,TargetFilename,MAX_PATH,NULL);
  1834. if(Add) {
  1835. //
  1836. // Fetch the size of the target file and add the operation
  1837. // to the disk space list.
  1838. //
  1839. if(_SetupGetSourceFileSize(LayoutInf,
  1840. LineInSection,
  1841. FileName,
  1842. NULL,
  1843. AltPlatformInfo,
  1844. &FileSize,
  1845. 0)) {
  1846. b = pSetupAddToDiskSpaceList(
  1847. DiskSpaceList,
  1848. FullTargetPath,
  1849. (LONGLONG)(LONG)FileSize,
  1850. Operation
  1851. );
  1852. if(!b) {
  1853. rc = GetLastError();
  1854. }
  1855. } else {
  1856. b = FALSE;
  1857. rc = GetLastError();
  1858. }
  1859. } else {
  1860. //
  1861. // Remove the operation from the disk space list.
  1862. //
  1863. b = pSetupRemoveFromDiskSpaceList(
  1864. DiskSpaceList,
  1865. FullTargetPath,
  1866. Operation
  1867. );
  1868. if (!b) {
  1869. rc = GetLastError();
  1870. }
  1871. }
  1872. } else {
  1873. b = FALSE;
  1874. rc = ERROR_INVALID_DATA;
  1875. }
  1876. SetLastError(rc);
  1877. return(b);
  1878. }
  1879. BOOL
  1880. pSetupAddToDiskSpaceList(
  1881. IN PDISK_SPACE_LIST DiskSpaceList,
  1882. IN PCTSTR TargetFilespec,
  1883. IN LONGLONG FileSize,
  1884. IN UINT Operation
  1885. )
  1886. /*++
  1887. Routine Description:
  1888. Worker routine to add an item to a disk space list.
  1889. Assumes locking is done by the caller.
  1890. Arguments:
  1891. DiskSpaceList - specifies pointer to disk space list structure
  1892. created by SetupCreateDiskSpaceList().
  1893. TargetFilespec - specifies filename of the file to add
  1894. to the disk space list. This will generally be a full win32
  1895. path, though this is not a requirement. If it is not then
  1896. standard win32 path semantics apply.
  1897. FileSize - supplies the (uncompressed) size of the file as it will
  1898. exist on the target when copied. Ignored for FILEOP_DELETE.
  1899. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  1900. Return Value:
  1901. Boolean value indicating outcome. If FALSE, GetLastError() returns
  1902. extended error information.
  1903. --*/
  1904. {
  1905. TCHAR Buffer[MAX_PATH];
  1906. DWORD rc;
  1907. BOOL b;
  1908. PTSTR DirPart;
  1909. PTSTR FilePart;
  1910. PTSTR drivespec;
  1911. TCHAR drivelet[4];
  1912. LONGLONG ExistingFileSize;
  1913. XDRIVE xDrive;
  1914. XDIRECTORY xDir;
  1915. XFILE xFile;
  1916. DWORD StringLength;
  1917. DWORD Hash;
  1918. LONG l;
  1919. DWORD SectorsPerCluster;
  1920. DWORD BytesPerSector;
  1921. DWORD TotalClusters;
  1922. DWORD FreeClusters;
  1923. if((Operation != FILEOP_DELETE) && (Operation != FILEOP_COPY) && (Operation != (UINT)(-1))) {
  1924. SetLastError(ERROR_INVALID_PARAMETER);
  1925. return(FALSE);
  1926. }
  1927. rc = NO_ERROR;
  1928. try {
  1929. rc = pParsePath(
  1930. TargetFilespec,
  1931. Buffer,
  1932. &DirPart,
  1933. &FilePart,
  1934. &ExistingFileSize,
  1935. DiskSpaceList->Flags
  1936. );
  1937. if(rc != NO_ERROR) {
  1938. goto c0;
  1939. }
  1940. //
  1941. // If we're not just doing the adjust case, drivespecs are not
  1942. // acceptable.
  1943. //
  1944. if((Operation != (UINT)(-1)) && (*FilePart == 0)) {
  1945. rc = ERROR_INVALID_PARAMETER;
  1946. goto c0;
  1947. }
  1948. //
  1949. // See whether the drive is already present in the drive list.
  1950. //
  1951. MYASSERT(DiskSpaceList->DrivesTable);
  1952. l = pStringTableLookUpString(
  1953. DiskSpaceList->DrivesTable,
  1954. Buffer,
  1955. &StringLength,
  1956. &Hash,
  1957. NULL,
  1958. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  1959. &xDrive,
  1960. sizeof(XDRIVE)
  1961. );
  1962. if(l == -1) {
  1963. //
  1964. // Determine cluster size for the drive and then add the drive
  1965. // to the drive list and create a string table for the
  1966. // directory list for this drive.
  1967. //
  1968. if(xDrive.DirsTable = pStringTableInitialize(sizeof(XDIRECTORY))) {
  1969. //
  1970. // The API is a little picky about what it is passed.
  1971. // For the local drive case we have to use x:\ but pParsePath
  1972. // sets things up so it's x:.
  1973. //
  1974. if(Buffer[1] == TEXT(':')) {
  1975. drivelet[0] = Buffer[0];
  1976. drivelet[1] = Buffer[1];
  1977. drivelet[2] = TEXT('\\');
  1978. drivelet[3] = 0;
  1979. drivespec = drivelet;
  1980. } else {
  1981. drivespec = Buffer;
  1982. }
  1983. b = GetDiskFreeSpace(
  1984. drivespec,
  1985. &SectorsPerCluster,
  1986. &BytesPerSector,
  1987. &FreeClusters,
  1988. &TotalClusters
  1989. );
  1990. if(!b) {
  1991. //
  1992. // This should probably be an error but there could be
  1993. // cases where people want to queue files say to a UNC path
  1994. // that isn't accessible now or something. Use reasonable defaults.
  1995. //
  1996. SectorsPerCluster = 1;
  1997. BytesPerSector = 512;
  1998. FreeClusters = 0;
  1999. TotalClusters = 0;
  2000. }
  2001. xDrive.SpaceRequired = 0;
  2002. xDrive.Slop = 0;
  2003. xDrive.BytesPerCluster = SectorsPerCluster * BytesPerSector;
  2004. l = pStringTableAddString(
  2005. DiskSpaceList->DrivesTable,
  2006. Buffer,
  2007. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2008. &xDrive,
  2009. sizeof(XDRIVE)
  2010. );
  2011. if(l == -1) {
  2012. pStringTableDestroy(xDrive.DirsTable);
  2013. }
  2014. }
  2015. }
  2016. if(l == -1) {
  2017. //
  2018. // Assume OOM.
  2019. //
  2020. rc = ERROR_NOT_ENOUGH_MEMORY;
  2021. goto c0;
  2022. }
  2023. if(Operation == (UINT)(-1)) {
  2024. //
  2025. // Only want to add the drive. Adjust the slop for the drive.
  2026. // rc is already set to NO_ERROR.
  2027. //
  2028. xDrive.Slop += FileSize;
  2029. if((DiskSpaceList->Flags & SPDSL_DISALLOW_NEGATIVE_ADJUST) && (xDrive.Slop < 0)) {
  2030. xDrive.Slop = 0;
  2031. }
  2032. pStringTableSetExtraData(
  2033. DiskSpaceList->DrivesTable,
  2034. l,
  2035. &xDrive,
  2036. sizeof(XDRIVE)
  2037. );
  2038. goto c0;
  2039. }
  2040. //
  2041. // Adjust sizes to account for cluster size.
  2042. //
  2043. FileSize = _AdjustSpace(FileSize,xDrive.BytesPerCluster);
  2044. if(ExistingFileSize != -1) {
  2045. ExistingFileSize = _AdjustSpace(ExistingFileSize,xDrive.BytesPerCluster);
  2046. }
  2047. //
  2048. // OK, xDrive has the drive info relevent for this file.
  2049. // Now handle the directory part. First see whether the directory
  2050. // is already present in the drive list.
  2051. //
  2052. l = pStringTableLookUpString(
  2053. xDrive.DirsTable,
  2054. DirPart,
  2055. &StringLength,
  2056. &Hash,
  2057. NULL,
  2058. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2059. &xDir,
  2060. sizeof(XDIRECTORY)
  2061. );
  2062. if(l == -1) {
  2063. //
  2064. // Add the directory to the directory string table.
  2065. //
  2066. if(xDir.FilesTable = pStringTableInitialize(sizeof(XFILE))) {
  2067. xDir.SpaceRequired = 0;
  2068. l = pStringTableAddString(
  2069. xDrive.DirsTable,
  2070. DirPart,
  2071. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2072. &xDir,
  2073. sizeof(XDIRECTORY)
  2074. );
  2075. if(l == -1) {
  2076. pStringTableDestroy(xDir.FilesTable);
  2077. }
  2078. }
  2079. }
  2080. if(l == -1) {
  2081. //
  2082. // Assume OOM.
  2083. //
  2084. rc = ERROR_NOT_ENOUGH_MEMORY;
  2085. goto c0;
  2086. }
  2087. //
  2088. // Finally, deal with the file itself.
  2089. // First see if it's in the list already.
  2090. //
  2091. l = pStringTableLookUpString(
  2092. xDir.FilesTable,
  2093. FilePart,
  2094. &StringLength,
  2095. &Hash,
  2096. NULL,
  2097. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2098. &xFile,
  2099. sizeof(XFILE)
  2100. );
  2101. if(l == -1) {
  2102. //
  2103. // The file is not already in there so put it in.
  2104. //
  2105. xFile.CurrentSize = ExistingFileSize;
  2106. xFile.NewSize = (Operation == FILEOP_DELETE) ? -1 : FileSize;
  2107. l = pStringTableAddString(
  2108. xDir.FilesTable,
  2109. FilePart,
  2110. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2111. &xFile,
  2112. sizeof(XFILE)
  2113. );
  2114. if(l == -1) {
  2115. rc = ERROR_NOT_ENOUGH_MEMORY;
  2116. goto c0;
  2117. }
  2118. } else {
  2119. if((xFile.CurrentSize == -1) && (xFile.NewSize == -1)) {
  2120. //
  2121. // This is a special "no-op" coding.
  2122. //
  2123. // The file is in there, but either the file was previously added
  2124. // for a delete op but it didn't exist on the disk, or it was removed
  2125. // via SetupRemoveFromDiskSpaceList().
  2126. //
  2127. xFile.CurrentSize = ExistingFileSize;
  2128. xFile.NewSize = (Operation == FILEOP_DELETE) ? -1 : FileSize;
  2129. } else {
  2130. //
  2131. // File is already in there. Remembering that deletes are done
  2132. // before copies when a file queue is committed and assuming
  2133. // that operations are put on the disk list in the same order they
  2134. // will eventually be done on the file queue, there are 4 cases:
  2135. //
  2136. // 1) On list as delete, caller wants to delete. Just refresh
  2137. // the existing file size in case it changed.
  2138. //
  2139. // 2) On list as delete, caller wants to copy. We treat this case
  2140. // as a copy and override the existing info on the disk space list.
  2141. //
  2142. // 3) On list as copy, caller wants to delete. At commit time the file
  2143. // will be deleted but then later copied; just refresh the existing
  2144. // file size, in case it changed.
  2145. //
  2146. // 4) On list as copy, caller wants to copy. Override existing
  2147. // info in this case.
  2148. //
  2149. // This actually boils down to the following: Always refresh the
  2150. // existing file size, and if the caller wants a copy, then
  2151. // remember the new size.
  2152. //
  2153. xFile.CurrentSize = ExistingFileSize;
  2154. if(Operation == FILEOP_COPY) {
  2155. xFile.NewSize = FileSize;
  2156. }
  2157. }
  2158. pStringTableSetExtraData(xDir.FilesTable,l,&xFile,sizeof(XFILE));
  2159. }
  2160. c0:
  2161. ;
  2162. } except(EXCEPTION_EXECUTE_HANDLER) {
  2163. rc = ERROR_INVALID_PARAMETER;
  2164. }
  2165. SetLastError(rc);
  2166. return(rc == NO_ERROR);
  2167. }
  2168. BOOL
  2169. pSetupRemoveFromDiskSpaceList(
  2170. IN PDISK_SPACE_LIST DiskSpace,
  2171. IN PCTSTR TargetFilespec,
  2172. IN UINT Operation
  2173. )
  2174. /*++
  2175. Routine Description:
  2176. Worker routine to remove a single delete or copy operation from a
  2177. disk space list.
  2178. Assumes locking is handled by the caller.
  2179. Arguments:
  2180. DiskSpaceList - specifies pointer to disk space list structure created by
  2181. SetupCreateDiskSpaceList().
  2182. TargetFilespec - specifies filename of the file to remove from
  2183. the disk space list. This will generally be a full win32
  2184. path, though this is not a requirement. If it is not then
  2185. standard win32 path semantics apply.
  2186. Operation - one of FILEOP_DELETE or FILEOP_COPY.
  2187. Return Value:
  2188. If the file was not in the list, the routine returns TRUE and
  2189. GetLastError() returns ERROR_INVALID_DRIVE or ERROR_INVALID_NAME.
  2190. If the file was in the list then upon success the routine returns
  2191. TRUE and GetLastError() returns NO_ERROR.
  2192. If the routine fails for some other reason it returns FALSE and GetLastError()
  2193. can be used to fetch extended error info.
  2194. --*/
  2195. {
  2196. DWORD rc;
  2197. BOOL b;
  2198. TCHAR Buffer[MAX_PATH];
  2199. PTSTR DirPart;
  2200. PTSTR FilePart;
  2201. LONGLONG ExistingFileSize;
  2202. LONG l;
  2203. DWORD StringLength;
  2204. DWORD Hash;
  2205. XDRIVE xDrive;
  2206. XDIRECTORY xDir;
  2207. XFILE xFile;
  2208. if((Operation != FILEOP_DELETE) && (Operation != FILEOP_COPY)) {
  2209. SetLastError(ERROR_INVALID_PARAMETER);
  2210. return(FALSE);
  2211. }
  2212. rc = NO_ERROR;
  2213. b = TRUE;
  2214. try {
  2215. //
  2216. // Split up the path into its constituent components.
  2217. //
  2218. rc = pParsePath(
  2219. TargetFilespec,
  2220. Buffer,
  2221. &DirPart,
  2222. &FilePart,
  2223. &ExistingFileSize,
  2224. DiskSpace->Flags
  2225. );
  2226. if(rc != NO_ERROR) {
  2227. goto c0;
  2228. }
  2229. //
  2230. // Drivespecs alone are not acceptable.
  2231. //
  2232. if(*FilePart == 0) {
  2233. rc = ERROR_INVALID_PARAMETER;
  2234. goto c0;
  2235. }
  2236. //
  2237. // Follow the trail down to the file string table.
  2238. //
  2239. MYASSERT(DiskSpace->DrivesTable);
  2240. l = pStringTableLookUpString(
  2241. DiskSpace->DrivesTable,
  2242. Buffer,
  2243. &StringLength,
  2244. &Hash,
  2245. NULL,
  2246. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2247. &xDrive,
  2248. sizeof(XDRIVE)
  2249. );
  2250. if(l == -1) {
  2251. //
  2252. // Return success but set last error to indicate condition.
  2253. //
  2254. rc = ERROR_INVALID_DRIVE;
  2255. goto c0;
  2256. }
  2257. MYASSERT(xDrive.DirsTable);
  2258. l = pStringTableLookUpString(
  2259. xDrive.DirsTable,
  2260. DirPart,
  2261. &StringLength,
  2262. &Hash,
  2263. NULL,
  2264. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2265. &xDir,
  2266. sizeof(XDIRECTORY)
  2267. );
  2268. if(l == -1) {
  2269. //
  2270. // Return success but set last error to indicate condition.
  2271. //
  2272. rc = ERROR_INVALID_NAME;
  2273. goto c0;
  2274. }
  2275. MYASSERT(xDir.FilesTable);
  2276. l = pStringTableLookUpString(
  2277. xDir.FilesTable,
  2278. FilePart,
  2279. &StringLength,
  2280. &Hash,
  2281. NULL,
  2282. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  2283. &xFile,
  2284. sizeof(XFILE)
  2285. );
  2286. if(l == -1) {
  2287. //
  2288. // Return success but set last error to indicate condition.
  2289. //
  2290. rc = ERROR_INVALID_NAME;
  2291. goto c0;
  2292. }
  2293. //
  2294. // Set special 'no-op' code for this file if the operations match.
  2295. //
  2296. if(Operation == FILEOP_DELETE) {
  2297. if(xFile.NewSize == -1) {
  2298. xFile.CurrentSize = -1;
  2299. }
  2300. } else {
  2301. if(xFile.NewSize != -1) {
  2302. xFile.NewSize = -1;
  2303. xFile.CurrentSize = -1;
  2304. }
  2305. }
  2306. pStringTableSetExtraData(xDir.FilesTable,l,&xFile,sizeof(XFILE));
  2307. c0:
  2308. ;
  2309. } except(EXCEPTION_EXECUTE_HANDLER) {
  2310. rc = ERROR_INVALID_PARAMETER;
  2311. b = FALSE;
  2312. }
  2313. SetLastError(rc);
  2314. return(b);
  2315. }
  2316. BOOL
  2317. pStringTableCBEnumDrives(
  2318. IN PVOID StringTable,
  2319. IN LONG StringId,
  2320. IN PCTSTR String,
  2321. IN PVOID ExtraData,
  2322. IN UINT ExtraDataSize,
  2323. IN LPARAM lParam
  2324. )
  2325. /*++
  2326. Routine Description:
  2327. Internal routine used as the callback when enumerating drives
  2328. in the disk space list. Writes the drivespec into a buffer
  2329. supplies to the enumeration routine.
  2330. Arguments:
  2331. Return Value:
  2332. --*/
  2333. {
  2334. PRETURN_BUFFER_INFO p;
  2335. UINT Length;
  2336. BOOL b;
  2337. PCVOID string;
  2338. UNREFERENCED_PARAMETER(StringTable);
  2339. UNREFERENCED_PARAMETER(StringId);
  2340. UNREFERENCED_PARAMETER(ExtraData);
  2341. UNREFERENCED_PARAMETER(ExtraDataSize);
  2342. p = (PRETURN_BUFFER_INFO)lParam;
  2343. #ifdef UNICODE
  2344. if(!p->IsUnicode) {
  2345. if(string = pSetupUnicodeToAnsi(String)) {
  2346. Length = lstrlenA(string) + 1;
  2347. } else {
  2348. return(FALSE);
  2349. }
  2350. } else
  2351. #endif
  2352. {
  2353. string = String;
  2354. Length = lstrlen(string) + 1;
  2355. }
  2356. p->RequiredSize += Length;
  2357. if(p->ReturnBuffer) {
  2358. if(p->RequiredSize <= p->ReturnBufferSize) {
  2359. //
  2360. // There's still room in the caller's buffer for this drive spec.
  2361. //
  2362. #ifdef UNICODE
  2363. if(!p->IsUnicode) {
  2364. lstrcpyA((PSTR)p->ReturnBuffer+p->RequiredSize-Length,string);
  2365. } else
  2366. #endif
  2367. lstrcpy((PTSTR)p->ReturnBuffer+p->RequiredSize-Length,string);
  2368. b = TRUE;
  2369. } else {
  2370. //
  2371. // Buffer is too small. Abort the enumeration.
  2372. //
  2373. b = FALSE;
  2374. }
  2375. } else {
  2376. //
  2377. // No buffer: just update the length required.
  2378. //
  2379. b = TRUE;
  2380. }
  2381. #ifdef UNICODE
  2382. if(string != String) {
  2383. MyFree(string);
  2384. }
  2385. #endif
  2386. return(b);
  2387. }
  2388. BOOL
  2389. pStringTableCBDelDrives(
  2390. IN PVOID StringTable,
  2391. IN LONG StringId,
  2392. IN PCTSTR String,
  2393. IN PVOID ExtraData,
  2394. IN UINT ExtraDataSize,
  2395. IN LPARAM lParam
  2396. )
  2397. /*++
  2398. Routine Description:
  2399. Internal routine used as the callback when calling pStringTableEnum
  2400. to determine which drives are part of a disk space list.
  2401. Enumerates directories on the drive, and then deletes the drives
  2402. string table.
  2403. Arguments:
  2404. Return Value:
  2405. --*/
  2406. {
  2407. PXDRIVE xDrive;
  2408. XDIRECTORY xDir;
  2409. BOOL b;
  2410. UNREFERENCED_PARAMETER(StringTable);
  2411. UNREFERENCED_PARAMETER(StringId);
  2412. UNREFERENCED_PARAMETER(String);
  2413. UNREFERENCED_PARAMETER(ExtraDataSize);
  2414. UNREFERENCED_PARAMETER(lParam);
  2415. //
  2416. // The extra data for the drives table is an XDRIVE structure.
  2417. //
  2418. xDrive = ExtraData;
  2419. //
  2420. // Enumerate the directory table for this drive. This destroys
  2421. // all of *those* string tables.
  2422. //
  2423. if(xDrive->DirsTable) {
  2424. b = pStringTableEnum(
  2425. xDrive->DirsTable,
  2426. &xDir,
  2427. sizeof(XDIRECTORY),
  2428. pStringTableCBDelDirs,
  2429. 0
  2430. );
  2431. pStringTableDestroy(xDrive->DirsTable);
  2432. } else {
  2433. b = FALSE;
  2434. }
  2435. return(b);
  2436. }
  2437. BOOL
  2438. pStringTableCBDelDirs(
  2439. IN PVOID StringTable,
  2440. IN LONG StringId,
  2441. IN PCTSTR String,
  2442. IN PVOID ExtraData,
  2443. IN UINT ExtraDataSize,
  2444. IN LPARAM lParam
  2445. )
  2446. /*++
  2447. Routine Description:
  2448. Internal routine used as the callback when calling pStringTableEnum
  2449. to determine which directories on a given drive are part of a
  2450. disk space list. Basically we just destroy the directory's file string table.
  2451. Arguments:
  2452. Return Value:
  2453. --*/
  2454. {
  2455. PXDIRECTORY xDir;
  2456. UNREFERENCED_PARAMETER(StringTable);
  2457. UNREFERENCED_PARAMETER(StringId);
  2458. UNREFERENCED_PARAMETER(String);
  2459. UNREFERENCED_PARAMETER(ExtraDataSize);
  2460. UNREFERENCED_PARAMETER(lParam);
  2461. //
  2462. // The extra data for the dirs table is an XDIRECTORY structure.
  2463. //
  2464. xDir = ExtraData;
  2465. if(xDir->FilesTable) {
  2466. pStringTableDestroy(xDir->FilesTable);
  2467. }
  2468. return(TRUE);
  2469. }
  2470. DWORD
  2471. pParsePath(
  2472. IN PCTSTR PathSpec,
  2473. OUT PTSTR Buffer,
  2474. OUT PTSTR *DirectoryPart,
  2475. OUT PTSTR *FilePart,
  2476. OUT LONGLONG *FileSize,
  2477. IN UINT Flags
  2478. )
  2479. /*++
  2480. Routine Description:
  2481. Given a (possibly relative or incomplete) pathspec, determine
  2482. the drive part, the directory part, and the filename parts and
  2483. return pointers thereto.
  2484. Arguments:
  2485. PathSpec - supplies the (possible relative) filename.
  2486. Buffer - must be MAX_PATH TCHAR elements. Receives the full win32
  2487. path, which is then carved up into drive, dir, and file parts.
  2488. When the function returns, the first part of Buffer is the
  2489. 0-terminated drive spec, not including a terminating \ char.
  2490. DirectoryPart - receives a pointer within Buffer to the first char
  2491. in the full path (which will not be \). The string starting
  2492. with that char will be nul-terminated.
  2493. FilePart - receives a pointer within Buffer to the nul-terminated
  2494. filename part (ie, the final component) of the win32 path
  2495. (no path sep chars are involved in that part of the path).
  2496. FileSize - receives the size of the file if it exists or -1 if not.
  2497. Flags - specifies flags.
  2498. SPDSL_IGNORE_DISK: this forces the routine to behave as if the file
  2499. does not exist on-disk.
  2500. Return Value:
  2501. Win32 error code indicating outcome.
  2502. --*/
  2503. {
  2504. DWORD rc;
  2505. WIN32_FIND_DATA FindData;
  2506. LPTSTR p;
  2507. rc = GetFullPathName(PathSpec,
  2508. MAX_PATH,
  2509. Buffer,
  2510. FilePart
  2511. );
  2512. if(!rc) {
  2513. return(GetLastError());
  2514. } else if(rc >= MAX_PATH) {
  2515. MYASSERT(0);
  2516. return(ERROR_BUFFER_OVERFLOW);
  2517. }
  2518. //
  2519. // Get the file size, if the file exists.
  2520. //
  2521. if(Flags & SPDSL_IGNORE_DISK) {
  2522. *FileSize = -1;
  2523. } else {
  2524. *FileSize = FileExists(Buffer,&FindData)
  2525. ? ((LONGLONG)FindData.nFileSizeHigh << 32) | FindData.nFileSizeLow
  2526. : -1;
  2527. }
  2528. //
  2529. // Figure the drive part. We have no choice but to assume that
  2530. // full paths are either x:\... or \\server\share\... because
  2531. // there isn't any solid way to ask win32 itself what the drive
  2532. // part of the path is.
  2533. //
  2534. // Stick a nul-terminator into the buffer to set off the drive part
  2535. // once we've found it. Note that drive roots are acceptable in
  2536. // the following forms:
  2537. //
  2538. // x:
  2539. // x:\
  2540. // \\server\share
  2541. // \\server\share\
  2542. //
  2543. if(Buffer[0] && (Buffer[1] == TEXT(':'))) {
  2544. if(Buffer[2] == 0) {
  2545. p = &Buffer[2];
  2546. } else {
  2547. if(Buffer[2] == TEXT('\\')) {
  2548. Buffer[2] = 0;
  2549. p = &Buffer[3];
  2550. } else {
  2551. return(ERROR_INVALID_DRIVE);
  2552. }
  2553. }
  2554. } else {
  2555. if((Buffer[0] == TEXT('\\')) && (Buffer[1] == TEXT('\\')) && Buffer[2]
  2556. && (p = _tcschr(&Buffer[3],TEXT('\\'))) && *(p+1) && (*(p+1) != TEXT('\\'))) {
  2557. //
  2558. // Dir part starts at next \, or it could be a drive root.
  2559. //
  2560. if(p = _tcschr(p+2,TEXT('\\'))) {
  2561. *p++ = 0;
  2562. } else {
  2563. p = _tcschr(p+2,0);
  2564. }
  2565. } else {
  2566. return(ERROR_INVALID_DRIVE);
  2567. }
  2568. }
  2569. //
  2570. // If we have a drive root, we're done. Set the dir and file parts
  2571. // to point at an empty string and return.
  2572. //
  2573. if(*p == 0) {
  2574. *DirectoryPart = p;
  2575. *FilePart = p;
  2576. return(NO_ERROR);
  2577. }
  2578. if(_tcschr(p,TEXT('\\'))) {
  2579. //
  2580. // There are at least 2 path components, so we have
  2581. // a directory and filename. We need to nul-terminate
  2582. // the directory part.
  2583. //
  2584. *DirectoryPart = p;
  2585. *(*FilePart - 1) = 0;
  2586. } else {
  2587. //
  2588. // There's only the one path component, so we have a file
  2589. // at the root of the drive. FilePart is already set from
  2590. // the call to GetFullPathName above. Set DirectoryPart
  2591. // to a nul-terminator to make it an empty string.
  2592. //
  2593. *DirectoryPart = Buffer+lstrlen(Buffer);
  2594. }
  2595. return(NO_ERROR);
  2596. }
  2597. BOOL
  2598. pStringTableCBRecalcFiles(
  2599. IN PVOID StringTable,
  2600. IN LONG StringId,
  2601. IN PCTSTR String,
  2602. IN PVOID ExtraData,
  2603. IN UINT ExtraDataSize,
  2604. IN LPARAM lParam
  2605. )
  2606. /*++
  2607. Routine Description:
  2608. Arguments:
  2609. Return Value:
  2610. --*/
  2611. {
  2612. PXFILE xFile;
  2613. LONGLONG Delta;
  2614. UNREFERENCED_PARAMETER(StringTable);
  2615. UNREFERENCED_PARAMETER(StringId);
  2616. UNREFERENCED_PARAMETER(String);
  2617. UNREFERENCED_PARAMETER(ExtraDataSize);
  2618. UNREFERENCED_PARAMETER(lParam);
  2619. //
  2620. // Extra data points to an XFILE.
  2621. //
  2622. xFile = ExtraData;
  2623. //
  2624. // Calculate the additional space the new file will require
  2625. // or the space that will be freed after the file is copied/deleted.
  2626. //
  2627. if(xFile->NewSize == -1) {
  2628. //
  2629. // File is being deleted. Account for the special 'no-op' coding.
  2630. //
  2631. Delta = (xFile->CurrentSize == -1) ? 0 : (0 - xFile->CurrentSize);
  2632. } else {
  2633. //
  2634. // File is being copied. Account for the fact that the file might not
  2635. // already exist on the disk.
  2636. //
  2637. Delta = (xFile->CurrentSize == -1) ? xFile->NewSize : (xFile->NewSize - xFile->CurrentSize);
  2638. }
  2639. //
  2640. // Update running accumulated total.
  2641. //
  2642. *(LONGLONG *)lParam += Delta;
  2643. return(TRUE);
  2644. }
  2645. BOOL
  2646. pStringTableCBRecalcDirs(
  2647. IN PVOID StringTable,
  2648. IN LONG StringId,
  2649. IN PCTSTR String,
  2650. IN PVOID ExtraData,
  2651. IN UINT ExtraDataSize,
  2652. IN LPARAM lParam
  2653. )
  2654. /*++
  2655. Routine Description:
  2656. Arguments:
  2657. Return Value:
  2658. --*/
  2659. {
  2660. PXDIRECTORY xDir;
  2661. XFILE xFile;
  2662. UNREFERENCED_PARAMETER(StringTable);
  2663. UNREFERENCED_PARAMETER(StringId);
  2664. UNREFERENCED_PARAMETER(String);
  2665. UNREFERENCED_PARAMETER(ExtraDataSize);
  2666. UNREFERENCED_PARAMETER(lParam);
  2667. //
  2668. // Extra data points to an XDIRECTORY.
  2669. //
  2670. xDir = ExtraData;
  2671. xDir->SpaceRequired = 0;
  2672. pStringTableEnum(
  2673. xDir->FilesTable,
  2674. &xFile,
  2675. sizeof(XFILE),
  2676. pStringTableCBRecalcFiles,
  2677. (LPARAM)&xDir->SpaceRequired
  2678. );
  2679. //
  2680. // Update running accumulated total.
  2681. //
  2682. *(LONGLONG *)lParam += xDir->SpaceRequired;
  2683. return(TRUE);
  2684. }
  2685. BOOL
  2686. pStringTableCBZeroDirsTableMember(
  2687. IN PVOID StringTable,
  2688. IN LONG StringId,
  2689. IN PCTSTR String,
  2690. IN PVOID ExtraData,
  2691. IN UINT ExtraDataSize,
  2692. IN LPARAM lParam
  2693. )
  2694. /*++
  2695. Routine Description:
  2696. Arguments:
  2697. Standard string table callback arguments.
  2698. Return Value:
  2699. --*/
  2700. {
  2701. UNREFERENCED_PARAMETER(String);
  2702. UNREFERENCED_PARAMETER(lParam);
  2703. if(lParam) {
  2704. ((PXDIRECTORY)ExtraData)->FilesTable = NULL;
  2705. } else {
  2706. ((PXDRIVE)ExtraData)->DirsTable = NULL;
  2707. }
  2708. MYASSERT(StringTable);
  2709. pStringTableSetExtraData(StringTable,StringId,ExtraData,ExtraDataSize);
  2710. return(TRUE);
  2711. }
  2712. BOOL
  2713. pStringTableCBDupMemberStringTable2(
  2714. IN PVOID StringTable,
  2715. IN LONG StringId,
  2716. IN PCTSTR String,
  2717. IN PVOID ExtraData,
  2718. IN UINT ExtraDataSize,
  2719. IN LPARAM lParam
  2720. )
  2721. /*++
  2722. Routine Description:
  2723. Arguments:
  2724. Standard string table callback arguments.
  2725. Return Value:
  2726. --*/
  2727. {
  2728. PXDIRECTORY xDir;
  2729. BOOL b;
  2730. UNREFERENCED_PARAMETER(StringTable);
  2731. UNREFERENCED_PARAMETER(String);
  2732. //
  2733. // Extra data is the XDIRECTORY structure in the old string table.
  2734. //
  2735. xDir = ExtraData;
  2736. //
  2737. // Duplicate the old FilesTable string table into the new table.
  2738. // We can reuse the xDir buffer.
  2739. //
  2740. xDir->FilesTable = pStringTableDuplicate(xDir->FilesTable);
  2741. if(!xDir->FilesTable) {
  2742. return(FALSE);
  2743. }
  2744. pStringTableSetExtraData((PVOID)lParam,StringId,ExtraData,ExtraDataSize);
  2745. return(TRUE);
  2746. }
  2747. BOOL
  2748. pStringTableCBDupMemberStringTable(
  2749. IN PVOID StringTable,
  2750. IN LONG StringId,
  2751. IN PCTSTR String,
  2752. IN PVOID ExtraData,
  2753. IN UINT ExtraDataSize,
  2754. IN LPARAM lParam
  2755. )
  2756. /*++
  2757. Routine Description:
  2758. Arguments:
  2759. Standard string table callback arguments.
  2760. Return Value:
  2761. --*/
  2762. {
  2763. PXDRIVE xDrive;
  2764. XDIRECTORY xDir;
  2765. BOOL b;
  2766. PVOID OldTable;
  2767. UNREFERENCED_PARAMETER(StringTable);
  2768. UNREFERENCED_PARAMETER(String);
  2769. //
  2770. // Extra data is the XDRIVE structure in the old string table.
  2771. //
  2772. xDrive = ExtraData;
  2773. //
  2774. // Duplicate the old DirsTable string table into the new table.
  2775. // We can reuse the xDrive buffer.
  2776. //
  2777. OldTable = xDrive->DirsTable;
  2778. xDrive->DirsTable = pStringTableDuplicate(xDrive->DirsTable);
  2779. if(!xDrive->DirsTable) {
  2780. return(FALSE);
  2781. }
  2782. pStringTableSetExtraData((PVOID)lParam,StringId,ExtraData,ExtraDataSize);
  2783. //
  2784. // Now zero out the FilesTable members of the XDIRECTORY extra data
  2785. // items in DirsTable string table.
  2786. //
  2787. pStringTableEnum(
  2788. xDrive->DirsTable,
  2789. &xDir,
  2790. sizeof(XDIRECTORY),
  2791. pStringTableCBZeroDirsTableMember,
  2792. 1
  2793. );
  2794. //
  2795. // Finally, take advantage of the fact that the ids in the table we just
  2796. // duplicated are the same in the old and new tables, to iterate the
  2797. // old table to duplicate its FilesTable string tables into the new
  2798. // string table. Clean up if failure.
  2799. //
  2800. b = pStringTableEnum(
  2801. OldTable,
  2802. &xDir,
  2803. sizeof(XDIRECTORY),
  2804. pStringTableCBDupMemberStringTable2,
  2805. (LPARAM)xDrive->DirsTable
  2806. );
  2807. if(!b) {
  2808. //
  2809. // Clean up.
  2810. //
  2811. pStringTableEnum(
  2812. xDrive->DirsTable,
  2813. &xDir,
  2814. sizeof(XDIRECTORY),
  2815. pStringTableCBDelDirs,
  2816. 0
  2817. );
  2818. }
  2819. return(b);
  2820. }
  2821. VOID
  2822. pRecalcSpace(
  2823. IN OUT PDISK_SPACE_LIST DiskSpaceList,
  2824. IN LONG DriveStringId
  2825. )
  2826. /*++
  2827. Routine Description:
  2828. Recalcuates the disk space required for a given drive by
  2829. traversing all the dirs and files that are on the space list
  2830. for the drive and performing additions/subtractions as necessary.
  2831. Assumes locking is handled by the caller and does not guard args.
  2832. Arguments:
  2833. DiskSpaceList - supplies the disk space list structure created
  2834. by SetupCreateDiskSpaceList().
  2835. DriveStringId - supplies the string id for the drive
  2836. (in DiskSpaceList->DrivesTable) for the drive to be updated.
  2837. Return Value:
  2838. None.
  2839. --*/
  2840. {
  2841. XDRIVE xDrive;
  2842. XDIRECTORY xDir;
  2843. if(DriveStringId == -1) {
  2844. return;
  2845. }
  2846. MYASSERT(DiskSpaceList->DrivesTable);
  2847. pStringTableGetExtraData(DiskSpaceList->DrivesTable,DriveStringId,&xDrive,sizeof(XDRIVE));
  2848. xDrive.SpaceRequired = 0;
  2849. pStringTableEnum(
  2850. xDrive.DirsTable,
  2851. &xDir,
  2852. sizeof(XDIRECTORY),
  2853. pStringTableCBRecalcDirs,
  2854. (LPARAM)&xDrive.SpaceRequired
  2855. );
  2856. pStringTableSetExtraData(DiskSpaceList->DrivesTable,DriveStringId,&xDrive,sizeof(XDRIVE));
  2857. }