Source code of Windows XP (NT5)
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.

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