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.

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