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.

2238 lines
51 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cablib.c
  5. Abstract:
  6. Implements wrappers for cabinet APIs
  7. Author:
  8. Calin Negreanu (calinn) 27-Apr-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include <cablib.h>
  14. #include <fci.h>
  15. #include <fdi.h>
  16. #include <fcntl.h>
  17. #include <crt\sys\stat.h>
  18. //
  19. // Includes
  20. //
  21. // None
  22. #define DBG_CABLIB "CabLib"
  23. //
  24. // Strings
  25. //
  26. // None
  27. //
  28. // Constants
  29. //
  30. #define VERIFY_HANDLE ((HANDLE) (-2))
  31. //
  32. // Macros
  33. //
  34. // None
  35. //
  36. // Types
  37. //
  38. typedef struct {
  39. PCSTR CabPath;
  40. PCSTR CabFileFormat;
  41. PCSTR CabDiskFormat;
  42. PCABGETCABINETNAMESA CabGetCabinetNames;
  43. HFCI FciHandle;
  44. ERF FciErrorStruct;
  45. CCAB FciCabParams;
  46. UINT FileCount;
  47. UINT CabCount;
  48. LONGLONG FileSize;
  49. LONGLONG CompressedSize;
  50. } FCI_CAB_HANDLEA, *PFCI_CAB_HANDLEA;
  51. typedef struct {
  52. PCWSTR CabPath;
  53. PCWSTR CabFileFormat;
  54. PCWSTR CabDiskFormat;
  55. PCABGETCABINETNAMESW CabGetCabinetNames;
  56. HFCI FciHandle;
  57. ERF FciErrorStruct;
  58. CCAB FciCabParams;
  59. UINT FileCount;
  60. UINT CabCount;
  61. LONGLONG FileSize;
  62. LONGLONG CompressedSize;
  63. } FCI_CAB_HANDLEW, *PFCI_CAB_HANDLEW;
  64. typedef struct {
  65. PCSTR CabPath;
  66. PCSTR CabFile;
  67. HFDI FdiHandle;
  68. ERF FdiErrorStruct;
  69. FDICABINETINFO FdiCabinetInfo;
  70. } FDI_CAB_HANDLEA, *PFDI_CAB_HANDLEA;
  71. typedef struct {
  72. PCWSTR CabPath;
  73. PCWSTR CabFile;
  74. HFDI FdiHandle;
  75. ERF FdiErrorStruct;
  76. FDICABINETINFO FdiCabinetInfo;
  77. } FDI_CAB_HANDLEW, *PFDI_CAB_HANDLEW;
  78. typedef struct {
  79. PCSTR ExtractPath;
  80. PCABNOTIFICATIONA CabNotificationA;
  81. } CAB_DATAA, *PCAB_DATAA;
  82. typedef struct {
  83. PCWSTR ExtractPath;
  84. PCABNOTIFICATIONW CabNotificationW;
  85. BOOL VerifyMode;
  86. } CAB_DATAW, *PCAB_DATAW;
  87. //
  88. // Globals
  89. //
  90. // None
  91. //
  92. // Macro expansion list
  93. //
  94. // None
  95. //
  96. // Private function prototypes
  97. //
  98. // None
  99. //
  100. // Macro expansion definition
  101. //
  102. // None
  103. //
  104. // Code
  105. //
  106. INT
  107. DIAMONDAPI
  108. pCabFilePlacedA (
  109. IN PCCAB FciCabParams,
  110. IN PSTR FileName,
  111. IN LONG FileSize,
  112. IN BOOL Continuation,
  113. IN PVOID Context
  114. )
  115. /*++
  116. Routine Description:
  117. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  118. --*/
  119. {
  120. PFCI_CAB_HANDLEA cabHandle;
  121. cabHandle = (PFCI_CAB_HANDLEA) Context;
  122. if (!cabHandle) {
  123. return 0;
  124. }
  125. cabHandle->FileCount++;
  126. cabHandle->FileSize += FileSize;
  127. return 0;
  128. }
  129. INT
  130. DIAMONDAPI
  131. pCabFilePlacedW (
  132. IN PCCAB FciCabParams,
  133. IN PSTR FileName,
  134. IN LONG FileSize,
  135. IN BOOL Continuation,
  136. IN PVOID Context
  137. )
  138. /*++
  139. Routine Description:
  140. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  141. --*/
  142. {
  143. PFCI_CAB_HANDLEW cabHandle;
  144. cabHandle = (PFCI_CAB_HANDLEW) Context;
  145. if (!cabHandle) {
  146. return 0;
  147. }
  148. cabHandle->FileCount++;
  149. cabHandle->FileSize += FileSize;
  150. return 0;
  151. }
  152. PVOID
  153. DIAMONDAPI
  154. pCabAlloc (
  155. IN ULONG Size
  156. )
  157. /*++
  158. Routine Description:
  159. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  160. --*/
  161. {
  162. return MemAlloc (g_hHeap, 0, Size);
  163. }
  164. VOID
  165. DIAMONDAPI
  166. pCabFree (
  167. IN PVOID Memory
  168. )
  169. /*++
  170. Routine Description:
  171. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  172. --*/
  173. {
  174. MemFree (g_hHeap, 0, Memory);
  175. }
  176. INT_PTR
  177. DIAMONDAPI
  178. pCabOpenA (
  179. IN PSTR FileName,
  180. IN INT oFlag,
  181. IN INT pMode,
  182. OUT PINT Error,
  183. IN PVOID Context
  184. )
  185. /*++
  186. Routine Description:
  187. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  188. --*/
  189. {
  190. HANDLE fileHandle;
  191. // oFlag and pMode are prepared for using _open. We won't do that
  192. // and it's a terrible waste of time to check each individual flags
  193. // We'll just assert these values.
  194. MYASSERT ((oFlag == (_O_CREAT | _O_TRUNC | _O_BINARY | _O_RDWR)) || (oFlag == (_O_CREAT | _O_EXCL | _O_BINARY | _O_RDWR)));
  195. MYASSERT (pMode == (_S_IREAD | _S_IWRITE));
  196. fileHandle = CreateFileA (
  197. FileName,
  198. GENERIC_READ | GENERIC_WRITE,
  199. 0,
  200. NULL,
  201. CREATE_ALWAYS,
  202. FILE_ATTRIBUTE_ARCHIVE,
  203. NULL
  204. );
  205. if (fileHandle == INVALID_HANDLE_VALUE) {
  206. *Error = GetLastError ();
  207. return -1;
  208. }
  209. *Error = 0;
  210. return (INT_PTR)fileHandle;
  211. }
  212. INT_PTR
  213. DIAMONDAPI
  214. pCabOpen1A (
  215. IN PSTR FileName,
  216. IN INT oFlag,
  217. IN INT pMode
  218. )
  219. /*++
  220. Routine Description:
  221. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  222. --*/
  223. {
  224. HANDLE fileHandle;
  225. // oFlag and pMode are prepared for using _open. We won't do that
  226. // and it's a terrible waste of time to check each individual flags
  227. // We'll just assert these values.
  228. MYASSERT (oFlag == _O_BINARY);
  229. fileHandle = CreateFileA (
  230. FileName,
  231. GENERIC_READ,
  232. FILE_SHARE_READ,
  233. NULL,
  234. OPEN_EXISTING,
  235. FILE_ATTRIBUTE_ARCHIVE,
  236. NULL
  237. );
  238. if (fileHandle == INVALID_HANDLE_VALUE) {
  239. return -1;
  240. }
  241. return (INT_PTR)fileHandle;
  242. }
  243. UINT
  244. DIAMONDAPI
  245. pCabRead (
  246. IN INT_PTR FileHandle,
  247. IN PVOID Buffer,
  248. IN UINT Size,
  249. OUT PINT Error,
  250. IN PVOID Context
  251. )
  252. /*++
  253. Routine Description:
  254. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  255. --*/
  256. {
  257. BOOL result;
  258. UINT bytesRead;
  259. result = ReadFile ((HANDLE)FileHandle, Buffer, Size, &bytesRead, NULL);
  260. if (!result) {
  261. *Error = GetLastError ();
  262. return ((UINT)(-1));
  263. }
  264. *Error = 0;
  265. return bytesRead;
  266. }
  267. UINT
  268. DIAMONDAPI
  269. pCabRead1 (
  270. IN INT_PTR FileHandle,
  271. IN PVOID Buffer,
  272. IN UINT Size
  273. )
  274. /*++
  275. Routine Description:
  276. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  277. --*/
  278. {
  279. BOOL result;
  280. UINT bytesRead;
  281. result = ReadFile ((HANDLE)FileHandle, Buffer, Size, &bytesRead, NULL);
  282. if (!result) {
  283. return ((UINT)(-1));
  284. }
  285. return bytesRead;
  286. }
  287. UINT
  288. DIAMONDAPI
  289. pCabWrite (
  290. IN INT_PTR FileHandle,
  291. IN PVOID Buffer,
  292. IN UINT Size,
  293. OUT PINT Error,
  294. IN PVOID Context
  295. )
  296. /*++
  297. Routine Description:
  298. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  299. --*/
  300. {
  301. BOOL result;
  302. DWORD dontCare;
  303. if (FileHandle == (INT_PTR) VERIFY_HANDLE) {
  304. return Size;
  305. }
  306. result = WriteFile ((HANDLE)FileHandle, Buffer, Size, &dontCare, NULL);
  307. if (!result) {
  308. *Error = GetLastError ();
  309. return ((UINT)(-1));
  310. }
  311. *Error = 0;
  312. return Size;
  313. }
  314. UINT
  315. DIAMONDAPI
  316. pCabWrite1 (
  317. IN INT_PTR FileHandle,
  318. IN PVOID Buffer,
  319. IN UINT Size
  320. )
  321. /*++
  322. Routine Description:
  323. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  324. --*/
  325. {
  326. BOOL result;
  327. DWORD dontCare;
  328. if (FileHandle == (INT_PTR) VERIFY_HANDLE) {
  329. return Size;
  330. }
  331. result = WriteFile ((HANDLE)FileHandle, Buffer, Size, &dontCare, NULL);
  332. if (!result) {
  333. return ((UINT)(-1));
  334. }
  335. return Size;
  336. }
  337. INT
  338. DIAMONDAPI
  339. pCabClose (
  340. IN INT_PTR FileHandle,
  341. OUT PINT Error,
  342. IN PVOID Context
  343. )
  344. /*++
  345. Routine Description:
  346. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  347. --*/
  348. {
  349. CloseHandle ((HANDLE)FileHandle);
  350. *Error = 0;
  351. return 0;
  352. }
  353. INT
  354. DIAMONDAPI
  355. pCabClose1 (
  356. IN INT_PTR FileHandle
  357. )
  358. /*++
  359. Routine Description:
  360. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  361. --*/
  362. {
  363. CloseHandle ((HANDLE)FileHandle);
  364. return 0;
  365. }
  366. LONG
  367. DIAMONDAPI
  368. pCabSeek (
  369. IN INT_PTR FileHandle,
  370. IN LONG Distance,
  371. IN INT SeekType,
  372. OUT PINT Error,
  373. IN PVOID Context
  374. )
  375. /*++
  376. Routine Description:
  377. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  378. --*/
  379. {
  380. DWORD result;
  381. DWORD seekType = FILE_BEGIN;
  382. switch (SeekType) {
  383. case SEEK_SET:
  384. seekType = FILE_BEGIN;
  385. break;
  386. case SEEK_CUR:
  387. seekType = FILE_CURRENT;
  388. break;
  389. case SEEK_END:
  390. seekType = FILE_END;
  391. break;
  392. }
  393. result = SetFilePointer ((HANDLE)FileHandle, Distance, NULL, seekType);
  394. if (result == INVALID_SET_FILE_POINTER) {
  395. *Error = GetLastError ();
  396. return -1;
  397. }
  398. *Error = 0;
  399. return ((LONG)(result));
  400. }
  401. LONG
  402. DIAMONDAPI
  403. pCabSeek1 (
  404. IN INT_PTR FileHandle,
  405. IN LONG Distance,
  406. IN INT SeekType
  407. )
  408. /*++
  409. Routine Description:
  410. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  411. --*/
  412. {
  413. DWORD result;
  414. DWORD seekType = FILE_BEGIN;
  415. switch (SeekType) {
  416. case SEEK_SET:
  417. seekType = FILE_BEGIN;
  418. break;
  419. case SEEK_CUR:
  420. seekType = FILE_CURRENT;
  421. break;
  422. case SEEK_END:
  423. seekType = FILE_END;
  424. break;
  425. }
  426. result = SetFilePointer ((HANDLE)FileHandle, Distance, NULL, seekType);
  427. if (result == INVALID_SET_FILE_POINTER) {
  428. return -1;
  429. }
  430. return ((LONG)(result));
  431. }
  432. INT
  433. DIAMONDAPI
  434. pCabDeleteA (
  435. IN PSTR FileName,
  436. OUT PINT Error,
  437. IN PVOID Context
  438. )
  439. /*++
  440. Routine Description:
  441. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  442. --*/
  443. {
  444. if (!DeleteFileA (FileName)) {
  445. *Error = GetLastError ();
  446. return -1;
  447. }
  448. *Error = 0;
  449. return 0;
  450. }
  451. BOOL
  452. DIAMONDAPI
  453. pCabGetTempFileA (
  454. OUT PSTR FileName,
  455. IN INT FileNameLen,
  456. IN PVOID Context
  457. )
  458. /*++
  459. Routine Description:
  460. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  461. --*/
  462. {
  463. CHAR tempPath[MAX_PATH];
  464. PSTR p;
  465. if (!GetTempPathA (ARRAYSIZE(tempPath), tempPath)) {
  466. return FALSE;
  467. }
  468. p = _mbsrchr (tempPath, '\\');
  469. if (p && !p[1]) {
  470. *p = 0;
  471. }
  472. if (!DoesFileExistA (tempPath)) {
  473. CreateDirectoryA (tempPath, NULL);
  474. }
  475. if (!GetTempFileNameA (tempPath, "cab", 0, FileName)) {
  476. return FALSE;
  477. }
  478. return TRUE;
  479. }
  480. BOOL
  481. DIAMONDAPI
  482. pCabGetNextCabinetA (
  483. IN PCCAB FciCabParams,
  484. IN ULONG PrevCabinetSize,
  485. IN PVOID Context
  486. )
  487. /*++
  488. Routine Description:
  489. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  490. --*/
  491. {
  492. PFCI_CAB_HANDLEA cabHandle;
  493. CHAR cabFile [1024];
  494. CHAR cabDisk [1024];
  495. cabHandle = (PFCI_CAB_HANDLEA) Context;
  496. if (!cabHandle) {
  497. return FALSE;
  498. }
  499. if (cabHandle->CabGetCabinetNames) {
  500. return cabHandle->CabGetCabinetNames (
  501. FciCabParams->szCabPath,
  502. CB_MAX_CAB_PATH,
  503. FciCabParams->szCab,
  504. CB_MAX_CABINET_NAME,
  505. FciCabParams->szDisk,
  506. CB_MAX_DISK_NAME,
  507. FciCabParams->iCab,
  508. &FciCabParams->iDisk
  509. );
  510. } else {
  511. FciCabParams->iDisk = FciCabParams->iCab;
  512. if (cabHandle->CabFileFormat) {
  513. wsprintfA (cabFile, cabHandle->CabFileFormat, FciCabParams->iCab);
  514. StringCopyByteCountA (FciCabParams->szCab, cabFile, CB_MAX_CABINET_NAME * sizeof (CHAR));
  515. }
  516. if (cabHandle->CabDiskFormat) {
  517. wsprintfA (cabDisk, cabHandle->CabDiskFormat, FciCabParams->iDisk);
  518. StringCopyByteCountA (FciCabParams->szDisk, cabDisk, CB_MAX_DISK_NAME * sizeof (CHAR));
  519. }
  520. }
  521. return TRUE;
  522. }
  523. BOOL
  524. DIAMONDAPI
  525. pCabGetNextCabinetW (
  526. IN PCCAB FciCabParams,
  527. IN ULONG PrevCabinetSize,
  528. IN PVOID Context
  529. )
  530. /*++
  531. Routine Description:
  532. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  533. --*/
  534. {
  535. PFCI_CAB_HANDLEW cabHandle;
  536. WCHAR cabPath [1024];
  537. WCHAR cabFile [1024];
  538. WCHAR cabDisk [1024];
  539. BOOL result;
  540. cabHandle = (PFCI_CAB_HANDLEW) Context;
  541. if (!cabHandle) {
  542. return FALSE;
  543. }
  544. if (cabHandle->CabGetCabinetNames) {
  545. result = cabHandle->CabGetCabinetNames (
  546. cabPath,
  547. CB_MAX_CAB_PATH,
  548. cabFile,
  549. CB_MAX_CABINET_NAME,
  550. cabDisk,
  551. CB_MAX_DISK_NAME,
  552. FciCabParams->iCab,
  553. &FciCabParams->iDisk
  554. );
  555. if (result) {
  556. KnownSizeUnicodeToDbcs (FciCabParams->szCabPath, cabPath);
  557. KnownSizeUnicodeToDbcs (FciCabParams->szCab, cabFile);
  558. KnownSizeUnicodeToDbcs (FciCabParams->szDisk, cabDisk);
  559. return TRUE;
  560. }
  561. return FALSE;
  562. } else {
  563. FciCabParams->iDisk = FciCabParams->iCab;
  564. if (cabHandle->CabFileFormat) {
  565. wsprintfW (cabFile, cabHandle->CabFileFormat, FciCabParams->iCab);
  566. KnownSizeUnicodeToDbcs (FciCabParams->szCab, cabFile);
  567. }
  568. if (cabHandle->CabDiskFormat) {
  569. wsprintfW (cabDisk, cabHandle->CabDiskFormat, FciCabParams->iDisk);
  570. KnownSizeUnicodeToDbcs (FciCabParams->szDisk, cabDisk);
  571. }
  572. }
  573. return TRUE;
  574. }
  575. LONG
  576. DIAMONDAPI
  577. pCabStatusA (
  578. IN UINT StatusType,
  579. IN ULONG Size1,
  580. IN ULONG Size2,
  581. IN PVOID Context
  582. )
  583. /*++
  584. Routine Description:
  585. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  586. --*/
  587. {
  588. PFCI_CAB_HANDLEA cabHandle;
  589. if (StatusType == statusCabinet) {
  590. cabHandle = (PFCI_CAB_HANDLEA) Context;
  591. if (!cabHandle) {
  592. return 0;
  593. }
  594. cabHandle->CabCount++;
  595. cabHandle->CompressedSize += (LONGLONG) Size2;
  596. }
  597. return 0;
  598. }
  599. LONG
  600. DIAMONDAPI
  601. pCabStatusW (
  602. IN UINT StatusType,
  603. IN ULONG Size1,
  604. IN ULONG Size2,
  605. IN PVOID Context
  606. )
  607. /*++
  608. Routine Description:
  609. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  610. --*/
  611. {
  612. PFCI_CAB_HANDLEW cabHandle;
  613. if (StatusType == statusCabinet) {
  614. cabHandle = (PFCI_CAB_HANDLEW) Context;
  615. if (!cabHandle) {
  616. return 0;
  617. }
  618. cabHandle->CabCount++;
  619. cabHandle->CompressedSize += (LONGLONG) Size2;
  620. }
  621. return 0;
  622. }
  623. INT_PTR
  624. DIAMONDAPI
  625. pCabGetOpenInfoA (
  626. IN PSTR FileName,
  627. OUT USHORT *Date,
  628. OUT USHORT *Time,
  629. OUT USHORT *Attributes,
  630. OUT PINT Error,
  631. IN PVOID Context
  632. )
  633. /*++
  634. Routine Description:
  635. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  636. --*/
  637. {
  638. WIN32_FIND_DATAA findData;
  639. FILETIME fileTime;
  640. HANDLE fileHandle;
  641. if (DoesFileExistExA (FileName, &findData)) {
  642. FileTimeToLocalFileTime (&findData.ftLastWriteTime, &fileTime);
  643. FileTimeToDosDateTime (&fileTime, Date, Time);
  644. /*
  645. * Mask out all other bits except these four, since other
  646. * bits are used by the cabinet format to indicate a
  647. * special meaning.
  648. */
  649. *Attributes = (USHORT) (findData.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
  650. fileHandle = CreateFileA (
  651. FileName,
  652. GENERIC_READ,
  653. FILE_SHARE_READ|FILE_SHARE_WRITE,
  654. NULL,
  655. OPEN_EXISTING,
  656. FILE_ATTRIBUTE_NORMAL,
  657. NULL
  658. );
  659. if (fileHandle == INVALID_HANDLE_VALUE) {
  660. *Error = GetLastError ();
  661. return -1;
  662. }
  663. *Error = 0;
  664. return (INT_PTR)fileHandle;
  665. } else {
  666. *Error = GetLastError ();
  667. return -1;
  668. }
  669. }
  670. BOOL
  671. pIsFullPathA (
  672. IN PCSTR PathToTest
  673. )
  674. {
  675. MBCHAR ch1;
  676. MBCHAR ch2;
  677. ch1 = _mbsnextc (PathToTest);
  678. _mbsinc (PathToTest);
  679. ch2 = _mbsnextc (PathToTest);
  680. if ((ch1 == '\\' && ch2 == '\\') ||
  681. (isalpha (ch1) && ch2 == '\\')
  682. ) {
  683. return TRUE;
  684. }
  685. return FALSE;
  686. }
  687. BOOL
  688. pIsFullPathW (
  689. IN PCWSTR PathToTest
  690. )
  691. {
  692. WCHAR ch1;
  693. WCHAR ch2;
  694. ch1 = *PathToTest++;
  695. ch2 = *PathToTest;
  696. if ((ch1 == '\\' && ch2 == '\\') ||
  697. (isalpha (ch1) && ch2 == '\\')
  698. ) {
  699. return TRUE;
  700. }
  701. return FALSE;
  702. }
  703. PCSTR
  704. pComputeDestPathA (
  705. IN PCSTR ExtractPath, OPTIONAL
  706. IN PCSTR PathStoredInCab
  707. )
  708. {
  709. PCSTR destFile;
  710. //
  711. // If ExtractPath is NULL, then use the path stored in the cab.
  712. // If the path stored in the cab is a full path, use only the file name.
  713. // Otherwise join ExtractPath with PathStoredInCab.
  714. //
  715. if (!ExtractPath) {
  716. destFile = DuplicatePathStringA (PathStoredInCab, 0);
  717. } else if (pIsFullPathA (PathStoredInCab)) {
  718. destFile = JoinPathsA (ExtractPath, GetFileNameFromPathA (PathStoredInCab));
  719. } else {
  720. destFile = JoinPathsA (ExtractPath, PathStoredInCab);
  721. }
  722. return destFile;
  723. }
  724. PCWSTR
  725. pComputeDestPathW (
  726. IN PCWSTR ExtractPath, OPTIONAL
  727. IN PCWSTR PathStoredInCab
  728. )
  729. {
  730. PCWSTR destFile;
  731. //
  732. // If ExtractPath is NULL, then use the path stored in the cab.
  733. // If the path stored in the cab is a full path, use only the file name.
  734. // Otherwise join ExtractPath with PathStoredInCab.
  735. //
  736. if (!ExtractPath) {
  737. destFile = DuplicatePathStringW (PathStoredInCab, 0);
  738. } else if (pIsFullPathW (PathStoredInCab)) {
  739. destFile = JoinPathsW (ExtractPath, GetFileNameFromPathW (PathStoredInCab));
  740. } else {
  741. destFile = JoinPathsW (ExtractPath, PathStoredInCab);
  742. }
  743. return destFile;
  744. }
  745. INT_PTR
  746. DIAMONDAPI
  747. pCabNotificationA (
  748. IN FDINOTIFICATIONTYPE FdiNotificationType,
  749. IN OUT PFDINOTIFICATION FdiNotification
  750. )
  751. /*++
  752. Routine Description:
  753. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  754. --*/
  755. {
  756. PCSTR destFile = NULL;
  757. HANDLE destHandle = NULL;
  758. DWORD attributes;
  759. FILETIME localFileTime;
  760. FILETIME fileTime;
  761. PCAB_DATAA cabData;
  762. INT createFlag;
  763. switch (FdiNotificationType) {
  764. case fdintCABINET_INFO: // General information about cabinet
  765. return 0;
  766. case fdintCOPY_FILE: // File to be copied
  767. cabData = (PCAB_DATAA)FdiNotification->pv;
  768. destFile = pComputeDestPathA (cabData->ExtractPath, FdiNotification->psz1);
  769. createFlag = TRUE;
  770. if (cabData->CabNotificationA) {
  771. createFlag = cabData->CabNotificationA (destFile);
  772. }
  773. if(-1 == createFlag){
  774. FreePathStringA (destFile);
  775. return -1;
  776. }
  777. if (createFlag) {
  778. MakeSurePathExistsA (FdiNotification->psz1, FALSE);
  779. SetFileAttributesA (destFile, FILE_ATTRIBUTE_NORMAL);
  780. destHandle = CreateFileA (
  781. destFile,
  782. GENERIC_READ|GENERIC_WRITE,
  783. 0,
  784. NULL,
  785. CREATE_ALWAYS,
  786. FILE_ATTRIBUTE_NORMAL,
  787. NULL
  788. );
  789. }
  790. FreePathStringA (destFile);
  791. return (INT_PTR)destHandle;
  792. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  793. cabData = (PCAB_DATAA)FdiNotification->pv;
  794. if (DosDateTimeToFileTime (FdiNotification->date, FdiNotification->time, &localFileTime)) {
  795. if (LocalFileTimeToFileTime (&localFileTime, &fileTime)) {
  796. SetFileTime ((HANDLE)FdiNotification->hf, &fileTime, &fileTime, &fileTime);
  797. }
  798. }
  799. destFile = pComputeDestPathA (cabData->ExtractPath, FdiNotification->psz1);
  800. CloseHandle ((HANDLE)FdiNotification->hf);
  801. attributes = (FdiNotification->attribs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
  802. SetFileAttributesA (destFile, attributes);
  803. FreePathStringA (destFile);
  804. return TRUE;
  805. case fdintPARTIAL_FILE: // First file in cabinet is continuation
  806. return 0;
  807. case fdintENUMERATE: // Enumeration status
  808. return 0;
  809. case fdintNEXT_CABINET: // File continued to next cabinet
  810. return 0;
  811. }
  812. return 0;
  813. }
  814. INT_PTR
  815. DIAMONDAPI
  816. pCabNotificationW (
  817. IN FDINOTIFICATIONTYPE FdiNotificationType,
  818. IN OUT PFDINOTIFICATION FdiNotification
  819. )
  820. /*++
  821. Routine Description:
  822. Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
  823. --*/
  824. {
  825. PCWSTR destFile = NULL;
  826. HANDLE destHandle = NULL;
  827. DWORD attributes;
  828. FILETIME localFileTime;
  829. FILETIME fileTime;
  830. PCAB_DATAW cabData;
  831. INT createFlag;
  832. PCWSTR cabFileSpecW;
  833. switch (FdiNotificationType) {
  834. case fdintCABINET_INFO: // General information about cabinet
  835. return 0;
  836. case fdintCOPY_FILE: // File to be copied
  837. cabFileSpecW = ConvertAtoW (FdiNotification->psz1);
  838. cabData = (PCAB_DATAW)FdiNotification->pv;
  839. destFile = pComputeDestPathW (cabData->ExtractPath, cabFileSpecW);
  840. FreeConvertedStr (cabFileSpecW);
  841. createFlag = TRUE;
  842. if (cabData->CabNotificationW) {
  843. createFlag = cabData->CabNotificationW (destFile);
  844. }
  845. if(-1 == createFlag){
  846. FreePathStringW (destFile);
  847. return -1;
  848. }
  849. if (createFlag) {
  850. if (!cabData->VerifyMode) {
  851. MakeSurePathExistsW (cabFileSpecW, FALSE);
  852. SetFileAttributesW (destFile, FILE_ATTRIBUTE_NORMAL);
  853. destHandle = CreateFileW (
  854. destFile,
  855. GENERIC_READ|GENERIC_WRITE,
  856. 0,
  857. NULL,
  858. CREATE_ALWAYS,
  859. FILE_ATTRIBUTE_NORMAL,
  860. NULL
  861. );
  862. } else {
  863. destHandle = VERIFY_HANDLE;
  864. }
  865. }
  866. FreePathStringW (destFile);
  867. return (INT_PTR)destHandle;
  868. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  869. cabData = (PCAB_DATAW)FdiNotification->pv;
  870. if (DosDateTimeToFileTime (FdiNotification->date, FdiNotification->time, &localFileTime)) {
  871. if (LocalFileTimeToFileTime (&localFileTime, &fileTime)) {
  872. SetFileTime ((HANDLE)FdiNotification->hf, &fileTime, &fileTime, &fileTime);
  873. }
  874. }
  875. cabFileSpecW = ConvertAtoW (FdiNotification->psz1);
  876. destFile = pComputeDestPathW (cabData->ExtractPath, cabFileSpecW);
  877. FreeConvertedStr (cabFileSpecW);
  878. CloseHandle ((HANDLE)FdiNotification->hf);
  879. attributes = (FdiNotification->attribs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
  880. SetFileAttributesW (destFile, attributes);
  881. FreePathStringW (destFile);
  882. return TRUE;
  883. case fdintPARTIAL_FILE: // First file in cabinet is continuation
  884. return 0;
  885. case fdintENUMERATE: // Enumeration status
  886. return 0;
  887. case fdintNEXT_CABINET: // File continued to next cabinet
  888. return 0;
  889. }
  890. return 0;
  891. }
  892. CCABHANDLE
  893. CabCreateCabinetA (
  894. IN PCSTR CabPath,
  895. IN PCSTR CabFileFormat,
  896. IN PCSTR CabDiskFormat,
  897. IN LONG MaxFileSize
  898. )
  899. /*++
  900. Routine Description:
  901. Creates a cabinet context. Caller may use this context for subsequent calls to
  902. CabAddFile.
  903. Arguments:
  904. CabPath - Specifies the path where the new cabinet file will be.
  905. CabFileFormat - Specifies (as for wsprintf) the format of the cabinet file name.
  906. CabDiskFormat - Specifies (as for wsprintf) the format of the cabinet disk name.
  907. MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
  908. Return Value:
  909. a valid CCABHANDLE if successful, NULL otherwise.
  910. --*/
  911. {
  912. PFCI_CAB_HANDLEA cabHandle;
  913. CHAR cabFile [1024];
  914. CHAR cabDisk [1024];
  915. if (!CabFileFormat) {
  916. return NULL;
  917. }
  918. if (MaxFileSize < 0) {
  919. return NULL;
  920. }
  921. if (MaxFileSize == 0) {
  922. MaxFileSize = 0x7FFFFFFF;
  923. }
  924. cabHandle = (PFCI_CAB_HANDLEA) MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEA));
  925. ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEA));
  926. if (CabPath) {
  927. cabHandle->CabPath = DuplicatePathStringA (CabPath, 0);
  928. }
  929. cabHandle->CabFileFormat = DuplicatePathStringA (CabFileFormat, 0);
  930. if (CabDiskFormat) {
  931. cabHandle->CabDiskFormat = DuplicatePathStringA (CabDiskFormat, 0);
  932. }
  933. // fill out the CCAB structure
  934. cabHandle->FciCabParams.cb = MaxFileSize;
  935. cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
  936. cabHandle->FciCabParams.cbReserveCFHeader = 0;
  937. cabHandle->FciCabParams.cbReserveCFFolder = 0;
  938. cabHandle->FciCabParams.cbReserveCFData = 0;
  939. cabHandle->FciCabParams.iCab = 1;
  940. cabHandle->FciCabParams.iDisk = 1;
  941. cabHandle->FciCabParams.setID = 0;
  942. if (CabPath) {
  943. StringCopyByteCountA (cabHandle->FciCabParams.szCabPath, CabPath, CB_MAX_CAB_PATH - 1);
  944. AppendWackA (cabHandle->FciCabParams.szCabPath);
  945. }
  946. if (CabDiskFormat) {
  947. wsprintfA (cabDisk, CabDiskFormat, cabHandle->FciCabParams.iDisk);
  948. StringCopyByteCountA (cabHandle->FciCabParams.szDisk, cabDisk, CB_MAX_DISK_NAME * sizeof (CHAR));
  949. }
  950. wsprintfA (cabFile, CabFileFormat, cabHandle->FciCabParams.iCab);
  951. StringCopyByteCountA (cabHandle->FciCabParams.szCab, cabFile, CB_MAX_CABINET_NAME * sizeof (CHAR));
  952. cabHandle->FciHandle = FCICreate (
  953. &cabHandle->FciErrorStruct,
  954. pCabFilePlacedA,
  955. pCabAlloc,
  956. pCabFree,
  957. pCabOpenA,
  958. pCabRead,
  959. pCabWrite,
  960. pCabClose,
  961. pCabSeek,
  962. pCabDeleteA,
  963. pCabGetTempFileA,
  964. &cabHandle->FciCabParams,
  965. cabHandle
  966. );
  967. if (!cabHandle->FciHandle) {
  968. if (cabHandle->CabPath) {
  969. FreePathStringA (cabHandle->CabPath);
  970. }
  971. if (cabHandle->CabFileFormat) {
  972. FreePathStringA (cabHandle->CabFileFormat);
  973. }
  974. if (cabHandle->CabDiskFormat) {
  975. FreePathStringA (cabHandle->CabDiskFormat);
  976. }
  977. MemFree (g_hHeap, 0, cabHandle);
  978. return NULL;
  979. }
  980. return ((CCABHANDLE)(cabHandle));
  981. }
  982. CCABHANDLE
  983. CabCreateCabinetW (
  984. IN PCWSTR CabPath,
  985. IN PCWSTR CabFileFormat,
  986. IN PCWSTR CabDiskFormat,
  987. IN LONG MaxFileSize
  988. )
  989. /*++
  990. Routine Description:
  991. Creates a cabinet context. Caller may use this context for subsequent calls to
  992. CabAddFile.
  993. Arguments:
  994. CabPath - Specifies the path where the new cabinet file will be.
  995. CabFileFormat - Specifies (as for wsprintf) the format of the cabinet file name.
  996. CabDiskFormat - Specifies (as for wsprintf) the format of the cabinet disk name.
  997. MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
  998. Return Value:
  999. a valid CCABHANDLE if successful, NULL otherwise.
  1000. --*/
  1001. {
  1002. PFCI_CAB_HANDLEW cabHandle;
  1003. WCHAR cabFile [1024];
  1004. WCHAR cabDisk [1024];
  1005. if (!CabFileFormat) {
  1006. return NULL;
  1007. }
  1008. if (MaxFileSize < 0) {
  1009. return NULL;
  1010. }
  1011. if (MaxFileSize == 0) {
  1012. MaxFileSize = 0x7FFFFFFF;
  1013. }
  1014. cabHandle = (PFCI_CAB_HANDLEW) MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEW));
  1015. ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEW));
  1016. if (CabPath) {
  1017. cabHandle->CabPath = DuplicatePathStringW (CabPath, 0);
  1018. }
  1019. cabHandle->CabFileFormat = DuplicatePathStringW (CabFileFormat, 0);
  1020. if (CabDiskFormat) {
  1021. cabHandle->CabDiskFormat = DuplicatePathStringW (CabDiskFormat, 0);
  1022. }
  1023. // fill out the CCAB structure
  1024. cabHandle->FciCabParams.cb = MaxFileSize;
  1025. cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
  1026. cabHandle->FciCabParams.cbReserveCFHeader = 0;
  1027. cabHandle->FciCabParams.cbReserveCFFolder = 0;
  1028. cabHandle->FciCabParams.cbReserveCFData = 0;
  1029. cabHandle->FciCabParams.iCab = 1;
  1030. cabHandle->FciCabParams.iDisk = 1;
  1031. cabHandle->FciCabParams.setID = 0;
  1032. if (CabPath) {
  1033. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCabPath, CabPath);
  1034. AppendWackA (cabHandle->FciCabParams.szCabPath);
  1035. }
  1036. if (CabDiskFormat) {
  1037. wsprintfW (cabDisk, CabDiskFormat, cabHandle->FciCabParams.iDisk);
  1038. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szDisk, cabDisk);
  1039. }
  1040. wsprintfW (cabFile, CabFileFormat, cabHandle->FciCabParams.iCab);
  1041. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCab, cabFile);
  1042. cabHandle->FciHandle = FCICreate (
  1043. &cabHandle->FciErrorStruct,
  1044. pCabFilePlacedW,
  1045. pCabAlloc,
  1046. pCabFree,
  1047. pCabOpenA,
  1048. pCabRead,
  1049. pCabWrite,
  1050. pCabClose,
  1051. pCabSeek,
  1052. pCabDeleteA,
  1053. pCabGetTempFileA,
  1054. &cabHandle->FciCabParams,
  1055. cabHandle
  1056. );
  1057. if (!cabHandle->FciHandle) {
  1058. if (cabHandle->CabPath) {
  1059. FreePathStringW (cabHandle->CabPath);
  1060. }
  1061. if (cabHandle->CabFileFormat) {
  1062. FreePathStringW (cabHandle->CabFileFormat);
  1063. }
  1064. if (cabHandle->CabDiskFormat) {
  1065. FreePathStringW (cabHandle->CabDiskFormat);
  1066. }
  1067. MemFree (g_hHeap, 0, cabHandle);
  1068. return NULL;
  1069. }
  1070. return ((CCABHANDLE)(cabHandle));
  1071. }
  1072. CCABHANDLE
  1073. CabCreateCabinetExA (
  1074. IN PCABGETCABINETNAMESA CabGetCabinetNames,
  1075. IN LONG MaxFileSize
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. Creates a cabinet context. Caller may use this context for subsequent calls to
  1080. CabAddFile.
  1081. Arguments:
  1082. CabGetCabinetNames - Specifies a callback used to decide cabinet path, cabinet name and disk name.
  1083. MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
  1084. Return Value:
  1085. a valid CCABHANDLE if successful, NULL otherwise.
  1086. --*/
  1087. {
  1088. PFCI_CAB_HANDLEA cabHandle;
  1089. if (!CabGetCabinetNames) {
  1090. return NULL;
  1091. }
  1092. if (MaxFileSize < 0) {
  1093. return NULL;
  1094. }
  1095. if (MaxFileSize == 0) {
  1096. MaxFileSize = 0x80000000;
  1097. }
  1098. cabHandle = MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEA));
  1099. ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEA));
  1100. cabHandle->CabGetCabinetNames = CabGetCabinetNames;
  1101. // fill out the CCAB structure
  1102. cabHandle->FciCabParams.cb = MaxFileSize;
  1103. cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
  1104. cabHandle->FciCabParams.cbReserveCFHeader = 0;
  1105. cabHandle->FciCabParams.cbReserveCFFolder = 0;
  1106. cabHandle->FciCabParams.cbReserveCFData = 0;
  1107. cabHandle->FciCabParams.iCab = 1;
  1108. cabHandle->FciCabParams.iDisk = 1;
  1109. cabHandle->FciCabParams.setID = 0;
  1110. if (!CabGetCabinetNames (
  1111. cabHandle->FciCabParams.szCabPath,
  1112. CB_MAX_CAB_PATH,
  1113. cabHandle->FciCabParams.szCab,
  1114. CB_MAX_CABINET_NAME,
  1115. cabHandle->FciCabParams.szDisk,
  1116. CB_MAX_DISK_NAME,
  1117. cabHandle->FciCabParams.iCab,
  1118. &cabHandle->FciCabParams.iDisk
  1119. )) {
  1120. return NULL;
  1121. }
  1122. cabHandle->FciHandle = FCICreate (
  1123. &cabHandle->FciErrorStruct,
  1124. pCabFilePlacedA,
  1125. pCabAlloc,
  1126. pCabFree,
  1127. pCabOpenA,
  1128. pCabRead,
  1129. pCabWrite,
  1130. pCabClose,
  1131. pCabSeek,
  1132. pCabDeleteA,
  1133. pCabGetTempFileA,
  1134. &cabHandle->FciCabParams,
  1135. cabHandle
  1136. );
  1137. if (!cabHandle->FciHandle) {
  1138. if (cabHandle->CabPath) {
  1139. FreePathStringA (cabHandle->CabPath);
  1140. }
  1141. if (cabHandle->CabFileFormat) {
  1142. FreePathStringA (cabHandle->CabFileFormat);
  1143. }
  1144. if (cabHandle->CabDiskFormat) {
  1145. FreePathStringA (cabHandle->CabDiskFormat);
  1146. }
  1147. MemFree (g_hHeap, 0, cabHandle);
  1148. return NULL;
  1149. }
  1150. return ((CCABHANDLE)(cabHandle));
  1151. }
  1152. CCABHANDLE
  1153. CabCreateCabinetExW (
  1154. IN PCABGETCABINETNAMESW CabGetCabinetNames,
  1155. IN LONG MaxFileSize
  1156. )
  1157. /*++
  1158. Routine Description:
  1159. Creates a cabinet context. Caller may use this context for subsequent calls to
  1160. CabAddFile.
  1161. Arguments:
  1162. CabGetCabinetNames - Specifies a callback used to decide cabinet path, cabinet name and disk name.
  1163. MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
  1164. Return Value:
  1165. a valid CCABHANDLE if successful, NULL otherwise.
  1166. --*/
  1167. {
  1168. PFCI_CAB_HANDLEW cabHandle;
  1169. WCHAR cabPath [1024];
  1170. WCHAR cabFile [1024];
  1171. WCHAR cabDisk [1024];
  1172. if (!CabGetCabinetNames) {
  1173. return NULL;
  1174. }
  1175. if (MaxFileSize < 0) {
  1176. return NULL;
  1177. }
  1178. if (MaxFileSize == 0) {
  1179. MaxFileSize = 0x80000000;
  1180. }
  1181. cabHandle = MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEW));
  1182. ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEW));
  1183. cabHandle->CabGetCabinetNames = CabGetCabinetNames;
  1184. // fill out the CCAB structure
  1185. cabHandle->FciCabParams.cb = MaxFileSize;
  1186. cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
  1187. cabHandle->FciCabParams.cbReserveCFHeader = 0;
  1188. cabHandle->FciCabParams.cbReserveCFFolder = 0;
  1189. cabHandle->FciCabParams.cbReserveCFData = 0;
  1190. cabHandle->FciCabParams.iCab = 1;
  1191. cabHandle->FciCabParams.iDisk = 1;
  1192. cabHandle->FciCabParams.setID = 0;
  1193. if (!CabGetCabinetNames (
  1194. cabPath,
  1195. CB_MAX_CAB_PATH,
  1196. cabFile,
  1197. CB_MAX_CABINET_NAME,
  1198. cabDisk,
  1199. CB_MAX_DISK_NAME,
  1200. cabHandle->FciCabParams.iCab,
  1201. &cabHandle->FciCabParams.iDisk
  1202. )) {
  1203. return NULL;
  1204. }
  1205. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCabPath, cabPath);
  1206. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCab, cabFile);
  1207. KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szDisk, cabDisk);
  1208. cabHandle->FciHandle = FCICreate (
  1209. &cabHandle->FciErrorStruct,
  1210. pCabFilePlacedW,
  1211. pCabAlloc,
  1212. pCabFree,
  1213. pCabOpenA,
  1214. pCabRead,
  1215. pCabWrite,
  1216. pCabClose,
  1217. pCabSeek,
  1218. pCabDeleteA,
  1219. pCabGetTempFileA,
  1220. &cabHandle->FciCabParams,
  1221. cabHandle
  1222. );
  1223. if (!cabHandle->FciHandle) {
  1224. if (cabHandle->CabPath) {
  1225. FreePathStringW (cabHandle->CabPath);
  1226. }
  1227. if (cabHandle->CabFileFormat) {
  1228. FreePathStringW (cabHandle->CabFileFormat);
  1229. }
  1230. if (cabHandle->CabDiskFormat) {
  1231. FreePathStringW (cabHandle->CabDiskFormat);
  1232. }
  1233. MemFree (g_hHeap, 0, cabHandle);
  1234. return NULL;
  1235. }
  1236. return ((CCABHANDLE)(cabHandle));
  1237. }
  1238. BOOL
  1239. CabAddFileToCabinetA (
  1240. IN CCABHANDLE CabHandle,
  1241. IN PCSTR FileName,
  1242. IN PCSTR StoredName
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. Compresses and adds a file to a cabinet context.
  1247. Arguments:
  1248. CabHandle - Specifies cabinet context.
  1249. FileName - Specifies the file to be added.
  1250. StoredName - Specifies the name to be stored in the cabinet file.
  1251. Return Value:
  1252. TRUE if successful, FALSE otherwise.
  1253. --*/
  1254. {
  1255. PFCI_CAB_HANDLEA cabHandle;
  1256. cabHandle = (PFCI_CAB_HANDLEA) CabHandle;
  1257. if (cabHandle == NULL) {
  1258. return FALSE;
  1259. }
  1260. if (cabHandle->FciHandle == NULL) {
  1261. return FALSE;
  1262. }
  1263. return FCIAddFile (
  1264. cabHandle->FciHandle,
  1265. (PSTR)FileName,
  1266. (PSTR)StoredName,
  1267. FALSE,
  1268. pCabGetNextCabinetA,
  1269. pCabStatusA,
  1270. pCabGetOpenInfoA,
  1271. tcompTYPE_MSZIP
  1272. );
  1273. }
  1274. BOOL
  1275. CabAddFileToCabinetW (
  1276. IN CCABHANDLE CabHandle,
  1277. IN PCWSTR FileName,
  1278. IN PCWSTR StoredName
  1279. )
  1280. /*++
  1281. Routine Description:
  1282. Compresses and adds a file to a cabinet context.
  1283. Arguments:
  1284. CabHandle - Specifies cabinet context.
  1285. FileName - Specifies the file to be added.
  1286. StoredName - Specifies the name to be stored in the cabinet file.
  1287. FileCount - Specifies a count of files, receives the updated count
  1288. when cabinet files are created
  1289. FileSize - Specifies the number of bytes used by the file, receives
  1290. the updated size
  1291. Return Value:
  1292. TRUE if successful, FALSE otherwise.
  1293. --*/
  1294. {
  1295. PFCI_CAB_HANDLEW cabHandle;
  1296. CHAR ansiFileName [1024];
  1297. CHAR ansiStoredName [1024];
  1298. cabHandle = (PFCI_CAB_HANDLEW) CabHandle;
  1299. if (cabHandle == NULL) {
  1300. return FALSE;
  1301. }
  1302. if (cabHandle->FciHandle == NULL) {
  1303. return FALSE;
  1304. }
  1305. KnownSizeUnicodeToDbcs (ansiFileName, FileName);
  1306. KnownSizeUnicodeToDbcs (ansiStoredName, StoredName);
  1307. return FCIAddFile (
  1308. cabHandle->FciHandle,
  1309. ansiFileName,
  1310. ansiStoredName,
  1311. FALSE,
  1312. pCabGetNextCabinetW,
  1313. pCabStatusW,
  1314. pCabGetOpenInfoA,
  1315. tcompTYPE_MSZIP
  1316. );
  1317. }
  1318. BOOL
  1319. CabFlushAndCloseCabinetExA (
  1320. IN CCABHANDLE CabHandle,
  1321. OUT PUINT FileCount, OPTIONAL
  1322. OUT PLONGLONG FileSize, OPTIONAL
  1323. OUT PUINT CabFileCount, OPTIONAL
  1324. OUT PLONGLONG CabFileSize OPTIONAL
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. Completes a cabinet file and closes its context.
  1329. Arguments:
  1330. CabHandle - Specifies cabinet context.
  1331. FileCount - Receives the number of files added to the cab
  1332. FileSize - Receives the size of all files before compression
  1333. CabFileCount - Receives the number of cabinet files created
  1334. CabFileSize - Receives the size of all cabinet files
  1335. Return Value:
  1336. TRUE if successful, FALSE otherwise.
  1337. --*/
  1338. {
  1339. PFCI_CAB_HANDLEA cabHandle;
  1340. BOOL result = FALSE;
  1341. cabHandle = (PFCI_CAB_HANDLEA) CabHandle;
  1342. if (cabHandle == NULL) {
  1343. return FALSE;
  1344. }
  1345. if (cabHandle->FciHandle == NULL) {
  1346. return FALSE;
  1347. }
  1348. if (FCIFlushCabinet (
  1349. cabHandle->FciHandle,
  1350. FALSE,
  1351. pCabGetNextCabinetA,
  1352. pCabStatusA
  1353. )) {
  1354. if (cabHandle->CabPath) {
  1355. FreePathStringA (cabHandle->CabPath);
  1356. }
  1357. if (cabHandle->CabFileFormat) {
  1358. FreePathStringA (cabHandle->CabFileFormat);
  1359. }
  1360. if (cabHandle->CabDiskFormat) {
  1361. FreePathStringA (cabHandle->CabDiskFormat);
  1362. }
  1363. result = FCIDestroy (cabHandle->FciHandle);
  1364. if (FileCount) {
  1365. *FileCount = cabHandle->FileCount;
  1366. }
  1367. if (FileSize) {
  1368. *FileSize = cabHandle->FileSize;
  1369. }
  1370. if (CabFileCount) {
  1371. *CabFileCount = cabHandle->CabCount;
  1372. }
  1373. if (CabFileSize) {
  1374. *CabFileSize = cabHandle->CompressedSize;
  1375. }
  1376. MemFree (g_hHeap, 0, cabHandle);
  1377. }
  1378. return result;
  1379. }
  1380. BOOL
  1381. CabFlushAndCloseCabinetExW (
  1382. IN CCABHANDLE CabHandle,
  1383. OUT PUINT FileCount, OPTIONAL
  1384. OUT PLONGLONG FileSize, OPTIONAL
  1385. OUT PUINT CabFileCount, OPTIONAL
  1386. OUT PLONGLONG CabFileSize OPTIONAL
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. Completes a cabinet file and closes its context.
  1391. Arguments:
  1392. CabHandle - Specifies cabinet context.
  1393. FileCount - Receives the number of files added to the cab
  1394. FileSize - Receives the size of all files before compression
  1395. CabFileCount - Receives the number of cabinet files created
  1396. CabFileSize - Receives the size of all cabinet files
  1397. Return Value:
  1398. TRUE if successful, FALSE otherwise.
  1399. --*/
  1400. {
  1401. PFCI_CAB_HANDLEW cabHandle;
  1402. BOOL result = FALSE;
  1403. cabHandle = (PFCI_CAB_HANDLEW) CabHandle;
  1404. if (cabHandle == NULL) {
  1405. return FALSE;
  1406. }
  1407. if (cabHandle->FciHandle == NULL) {
  1408. return FALSE;
  1409. }
  1410. if (FCIFlushCabinet (
  1411. cabHandle->FciHandle,
  1412. FALSE,
  1413. pCabGetNextCabinetW,
  1414. pCabStatusW
  1415. )) {
  1416. if (cabHandle->CabPath) {
  1417. FreePathStringW (cabHandle->CabPath);
  1418. }
  1419. if (cabHandle->CabFileFormat) {
  1420. FreePathStringW (cabHandle->CabFileFormat);
  1421. }
  1422. if (cabHandle->CabDiskFormat) {
  1423. FreePathStringW (cabHandle->CabDiskFormat);
  1424. }
  1425. result = FCIDestroy (cabHandle->FciHandle);
  1426. if (FileCount) {
  1427. *FileCount = cabHandle->FileCount;
  1428. }
  1429. if (FileSize) {
  1430. *FileSize = cabHandle->FileSize;
  1431. }
  1432. if (CabFileCount) {
  1433. *CabFileCount = cabHandle->CabCount;
  1434. }
  1435. if (CabFileSize) {
  1436. *CabFileSize = cabHandle->CompressedSize;
  1437. }
  1438. MemFree (g_hHeap, 0, cabHandle);
  1439. }
  1440. return result;
  1441. }
  1442. OCABHANDLE
  1443. CabOpenCabinetA (
  1444. IN PCSTR FileName
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Creates a cabinet context for an existent cabinet file.
  1449. Arguments:
  1450. FileName - Specifies cabinet file name.
  1451. Return Value:
  1452. a valid OCABHANDLE if successful, NULL otherwise.
  1453. --*/
  1454. {
  1455. PFDI_CAB_HANDLEA cabHandle;
  1456. PSTR filePtr;
  1457. HANDLE fileHandle;
  1458. PCSTR fileName;
  1459. cabHandle = (PFDI_CAB_HANDLEA) MemAlloc (g_hHeap, 0, sizeof (FDI_CAB_HANDLEA));
  1460. ZeroMemory (cabHandle, sizeof (FDI_CAB_HANDLEA));
  1461. cabHandle->FdiHandle = FDICreate (
  1462. pCabAlloc,
  1463. pCabFree,
  1464. pCabOpen1A,
  1465. pCabRead1,
  1466. pCabWrite1,
  1467. pCabClose1,
  1468. pCabSeek1,
  1469. cpuUNKNOWN,
  1470. &cabHandle->FdiErrorStruct
  1471. );
  1472. if (!cabHandle->FdiHandle) {
  1473. MemFree (g_hHeap, 0, cabHandle);
  1474. return NULL;
  1475. }
  1476. fileName = DuplicatePathStringA (FileName, 0);
  1477. fileHandle = CreateFileA (
  1478. fileName,
  1479. GENERIC_READ|GENERIC_WRITE,
  1480. 0,
  1481. NULL,
  1482. OPEN_EXISTING,
  1483. FILE_ATTRIBUTE_NORMAL,
  1484. NULL
  1485. );
  1486. if (fileHandle == INVALID_HANDLE_VALUE) {
  1487. FreePathStringA (fileName);
  1488. MemFree (g_hHeap, 0, cabHandle);
  1489. return NULL;
  1490. }
  1491. if (!FDIIsCabinet (cabHandle->FdiHandle, (INT_PTR)fileHandle, &cabHandle->FdiCabinetInfo)) {
  1492. FreePathStringA (fileName);
  1493. CloseHandle (fileHandle);
  1494. MemFree (g_hHeap, 0, cabHandle);
  1495. return NULL;
  1496. }
  1497. CloseHandle (fileHandle);
  1498. filePtr = (PSTR)GetFileNameFromPathA (fileName);
  1499. if (!filePtr) {
  1500. FreePathStringA (fileName);
  1501. MemFree (g_hHeap, 0, cabHandle);
  1502. return NULL;
  1503. }
  1504. cabHandle->CabFile = DuplicatePathStringA (filePtr, 0);
  1505. *filePtr = 0;
  1506. cabHandle->CabPath = DuplicatePathStringA (fileName, 0);
  1507. FreePathStringA (fileName);
  1508. return ((CCABHANDLE)(cabHandle));
  1509. }
  1510. OCABHANDLE
  1511. CabOpenCabinetW (
  1512. IN PCWSTR FileName
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Creates a cabinet context for an existent cabinet file.
  1517. Arguments:
  1518. FileName - Specifies cabinet file name.
  1519. Return Value:
  1520. a valid OCABHANDLE if successful, NULL otherwise.
  1521. --*/
  1522. {
  1523. PFDI_CAB_HANDLEW cabHandle;
  1524. PWSTR filePtr;
  1525. HANDLE fileHandle;
  1526. PCWSTR fileName;
  1527. cabHandle = (PFDI_CAB_HANDLEW) MemAlloc (g_hHeap, 0, sizeof (FDI_CAB_HANDLEW));
  1528. ZeroMemory (cabHandle, sizeof (FDI_CAB_HANDLEW));
  1529. cabHandle->FdiHandle = FDICreate (
  1530. pCabAlloc,
  1531. pCabFree,
  1532. pCabOpen1A,
  1533. pCabRead1,
  1534. pCabWrite1,
  1535. pCabClose1,
  1536. pCabSeek1,
  1537. cpuUNKNOWN,
  1538. &cabHandle->FdiErrorStruct
  1539. );
  1540. if (!cabHandle->FdiHandle) {
  1541. MemFree (g_hHeap, 0, cabHandle);
  1542. return NULL;
  1543. }
  1544. fileName = DuplicatePathStringW (FileName, 0);
  1545. fileHandle = CreateFileW (
  1546. fileName,
  1547. GENERIC_READ|GENERIC_WRITE,
  1548. 0,
  1549. NULL,
  1550. OPEN_EXISTING,
  1551. FILE_ATTRIBUTE_NORMAL,
  1552. NULL
  1553. );
  1554. if (fileHandle == INVALID_HANDLE_VALUE) {
  1555. FreePathStringW (fileName);
  1556. MemFree (g_hHeap, 0, cabHandle);
  1557. return NULL;
  1558. }
  1559. if (!FDIIsCabinet (cabHandle->FdiHandle, (INT_PTR)fileHandle, &cabHandle->FdiCabinetInfo)) {
  1560. FreePathStringW (fileName);
  1561. CloseHandle (fileHandle);
  1562. MemFree (g_hHeap, 0, cabHandle);
  1563. return NULL;
  1564. }
  1565. CloseHandle (fileHandle);
  1566. filePtr = (PWSTR)GetFileNameFromPathW (fileName);
  1567. if (!filePtr) {
  1568. FreePathStringW (fileName);
  1569. MemFree (g_hHeap, 0, cabHandle);
  1570. return NULL;
  1571. }
  1572. cabHandle->CabFile = DuplicatePathStringW (filePtr, 0);
  1573. *filePtr = 0;
  1574. cabHandle->CabPath = DuplicatePathStringW (fileName, 0);
  1575. FreePathStringW (fileName);
  1576. return ((CCABHANDLE)(cabHandle));
  1577. }
  1578. BOOL
  1579. CabExtractAllFilesExA (
  1580. IN OCABHANDLE CabHandle,
  1581. IN PCSTR ExtractPath, OPTIONAL
  1582. IN PCABNOTIFICATIONA CabNotification OPTIONAL
  1583. )
  1584. /*++
  1585. Routine Description:
  1586. Extracts all files from a cabinet file.
  1587. Arguments:
  1588. CabHandle - Specifies cabinet context.
  1589. ExtractPath - Specifies the path to extract the files to.
  1590. Return Value:
  1591. TRUE if successful, FALSE otherwise.
  1592. --*/
  1593. {
  1594. PFDI_CAB_HANDLEA cabHandle;
  1595. CAB_DATAA cabData;
  1596. cabHandle = (PFDI_CAB_HANDLEA)CabHandle;
  1597. if (!cabHandle) {
  1598. return FALSE;
  1599. }
  1600. if (!cabHandle->FdiHandle) {
  1601. return FALSE;
  1602. }
  1603. cabData.ExtractPath = ExtractPath;
  1604. cabData.CabNotificationA = CabNotification;
  1605. return FDICopy (
  1606. cabHandle->FdiHandle,
  1607. (PSTR)cabHandle->CabFile,
  1608. (PSTR)cabHandle->CabPath,
  1609. 0,
  1610. pCabNotificationA,
  1611. NULL,
  1612. (PVOID)(&cabData)
  1613. );
  1614. }
  1615. BOOL
  1616. pCabExtractAllFilesExWorkerW (
  1617. IN OCABHANDLE CabHandle,
  1618. IN PCWSTR ExtractPath, OPTIONAL
  1619. IN PCABNOTIFICATIONW CabNotificationW, OPTIONAL
  1620. IN BOOL VerifyMode
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. Extracts all files from a cabinet file.
  1625. Arguments:
  1626. CabHandle - Specifies cabinet context.
  1627. ExtractPath - Specifies the path to extract the files to.
  1628. CabNotification - Specifies the notification callback function that is
  1629. called for every file in the cab
  1630. VerifyMode - Specifies TRUE if the cab should be verified, FALSE if it
  1631. should be extracted
  1632. Return Value:
  1633. TRUE if successful, FALSE otherwise.
  1634. --*/
  1635. {
  1636. PFDI_CAB_HANDLEW cabHandle;
  1637. CAB_DATAW cabData;
  1638. BOOL result;
  1639. PCSTR cabFileAnsi;
  1640. PCSTR cabPathAnsi;
  1641. cabHandle = (PFDI_CAB_HANDLEW)CabHandle;
  1642. if (!cabHandle) {
  1643. return FALSE;
  1644. }
  1645. if (!cabHandle->FdiHandle) {
  1646. return FALSE;
  1647. }
  1648. cabData.ExtractPath = ExtractPath;
  1649. cabData.CabNotificationW = CabNotificationW;
  1650. cabData.VerifyMode = VerifyMode;
  1651. cabFileAnsi = ConvertWtoA (cabHandle->CabFile);
  1652. cabPathAnsi = ConvertWtoA (cabHandle->CabPath);
  1653. result = FDICopy (
  1654. cabHandle->FdiHandle,
  1655. (PSTR) cabFileAnsi,
  1656. (PSTR) cabPathAnsi,
  1657. 0,
  1658. pCabNotificationW,
  1659. NULL,
  1660. (PVOID)(&cabData)
  1661. );
  1662. FreeConvertedStr (cabFileAnsi);
  1663. FreeConvertedStr (cabPathAnsi);
  1664. return result;
  1665. }
  1666. BOOL
  1667. CabExtractAllFilesExW (
  1668. IN OCABHANDLE CabHandle,
  1669. IN PCWSTR ExtractPath, OPTIONAL
  1670. IN PCABNOTIFICATIONW CabNotificationW OPTIONAL
  1671. )
  1672. {
  1673. return pCabExtractAllFilesExWorkerW (CabHandle, ExtractPath, CabNotificationW, FALSE);
  1674. }
  1675. BOOL
  1676. CabVerifyCabinet (
  1677. IN OCABHANDLE CabHandle
  1678. )
  1679. {
  1680. return pCabExtractAllFilesExWorkerW (CabHandle, NULL, NULL, TRUE);
  1681. }
  1682. BOOL
  1683. CabCloseCabinetA (
  1684. IN OCABHANDLE CabHandle
  1685. )
  1686. /*++
  1687. Routine Description:
  1688. Closes a cabinet file context.
  1689. Arguments:
  1690. CabHandle - Specifies cabinet context.
  1691. Return Value:
  1692. TRUE if successful, FALSE otherwise.
  1693. --*/
  1694. {
  1695. PFDI_CAB_HANDLEA cabHandle;
  1696. cabHandle = (PFDI_CAB_HANDLEA) CabHandle;
  1697. if (!cabHandle) {
  1698. return FALSE;
  1699. }
  1700. if (!cabHandle->FdiHandle) {
  1701. return FALSE;
  1702. }
  1703. if (FDIDestroy (cabHandle->FdiHandle)) {
  1704. if (cabHandle->CabPath) {
  1705. FreePathStringA (cabHandle->CabPath);
  1706. }
  1707. if (cabHandle->CabFile) {
  1708. FreePathStringA (cabHandle->CabFile);
  1709. }
  1710. MemFree (g_hHeap, 0, cabHandle);
  1711. return TRUE;
  1712. }
  1713. return FALSE;
  1714. }
  1715. BOOL
  1716. CabCloseCabinetW (
  1717. IN OCABHANDLE CabHandle
  1718. )
  1719. /*++
  1720. Routine Description:
  1721. Closes a cabinet file context.
  1722. Arguments:
  1723. CabHandle - Specifies cabinet context.
  1724. Return Value:
  1725. TRUE if successful, FALSE otherwise.
  1726. --*/
  1727. {
  1728. PFDI_CAB_HANDLEW cabHandle;
  1729. cabHandle = (PFDI_CAB_HANDLEW) CabHandle;
  1730. if (!cabHandle) {
  1731. return FALSE;
  1732. }
  1733. if (!cabHandle->FdiHandle) {
  1734. return FALSE;
  1735. }
  1736. if (FDIDestroy (cabHandle->FdiHandle)) {
  1737. if (cabHandle->CabPath) {
  1738. FreePathStringW (cabHandle->CabPath);
  1739. }
  1740. if (cabHandle->CabFile) {
  1741. FreePathStringW (cabHandle->CabFile);
  1742. }
  1743. MemFree (g_hHeap, 0, cabHandle);
  1744. return TRUE;
  1745. }
  1746. return FALSE;
  1747. }