Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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