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.

1100 lines
48 KiB

  1. /*** types.h - Common defines for FCI/FDI stuff -- goes into FCI/FDI.H
  2. *
  3. * Microsoft Confidential
  4. * Copyright (C) Microsoft Corporation 1993-1994
  5. * All Rights Reserved.
  6. *
  7. * History:
  8. * 03-Mar-1993 chuckst Merged from other files
  9. * 08-Mar-1994 bens Changed symbol to control recursive include
  10. * 09-Mar-1994 bens Cleanups for RESERVE modifications
  11. * 16-Mar-1994 bens Nuke padlong()
  12. * 21-Mar-1994 bens Spruce up comments
  13. * 22-Mar-1994 bens Add BIT16 test so we can build 16 or 32 bit!
  14. * 26-May-1994 bens Added Quantum compression definitions
  15. */
  16. #ifndef INCLUDED_TYPES_FCI_FDI
  17. #define INCLUDED_TYPES_FCI_FDI 1
  18. #pragma warning(disable:4121)
  19. //** Define away for 32-bit (NT/Chicago) build
  20. #ifndef HUGE
  21. #define HUGE
  22. #endif
  23. #ifndef FAR
  24. #define FAR
  25. #endif
  26. #ifndef DIAMONDAPI
  27. #define DIAMONDAPI __cdecl
  28. #endif
  29. //** Specify structure packing explicitly for clients of FDI
  30. #if !defined(unix) && !defined(_WIN64)
  31. #pragma pack(4)
  32. #endif /* !defined(unix) && !defined(_WIN64) */
  33. //** Don't redefine types defined in Win16 WINDOWS.H (_INC_WINDOWS)
  34. // or Win32 WINDOWS.H (_WINDOWS_)
  35. //
  36. #if !defined(_INC_WINDOWS) && !defined(_WINDOWS_)
  37. typedef int BOOL; /* f */
  38. typedef unsigned char BYTE; /* b */
  39. typedef unsigned int UINT; /* ui */
  40. typedef unsigned short USHORT; /* us */
  41. typedef unsigned long ULONG; /* ul */
  42. #endif // _INC_WINDOWS
  43. typedef unsigned long CHECKSUM; /* csum */
  44. typedef unsigned long UOFF; /* uoff - uncompressed offset */
  45. typedef unsigned long COFF; /* coff - cabinet file offset */
  46. #ifndef TRUE
  47. #define TRUE 1
  48. #endif
  49. #ifndef FALSE
  50. #define FALSE 0
  51. #endif
  52. #ifndef NULL
  53. #define NULL 0
  54. #endif
  55. /*** ERF - Error structure
  56. *
  57. * This structure returns error information from FCI/FDI. The caller should
  58. * not modify this structure.
  59. */
  60. typedef struct {
  61. int erfOper; // FCI/FDI error code -- see FDIERROR_XXX
  62. // and FCIERR_XXX equates for details.
  63. int erfType; // Optional error value filled in by FCI/FDI.
  64. // For FCI, this is usually the C run-time
  65. // *errno* value.
  66. BOOL fError; // TRUE => error present
  67. } ERF; /* erf */
  68. typedef ERF FAR *PERF; /* perf */
  69. #ifdef _DEBUG
  70. // don't hide statics from map during debugging
  71. #define STATIC
  72. #else // !DEBUG
  73. #define STATIC static
  74. #endif // !DEBUG
  75. #define CB_MAX_CHUNK 32768U
  76. #define CB_MAX_DISK 0x7ffffffL
  77. #define CB_MAX_FILENAME 256
  78. #define CB_MAX_CABINET_NAME 256
  79. #define CB_MAX_CAB_PATH 256
  80. #define CB_MAX_DISK_NAME 256
  81. /*** FNALLOC - Memory Allocation
  82. * FNFREE - Memory Free
  83. *
  84. * These are modeled after the C run-time routines malloc() and free()
  85. * (16-bit clients please note -- the size is a ULONG, so you may need
  86. * to write a wrapper routine for halloc!). FDI expects error
  87. * handling to be identical to these C run-time routines.
  88. *
  89. * As long as you faithfully copy the semantics of malloc() and free(),
  90. * you can supply any functions you like!
  91. *
  92. * WARNING: You should never assume anything about the sequence of
  93. * PFNALLOC and PFNFREE calls -- incremental releases of
  94. * Diamond/FDI may have radically different numbers of
  95. * PFNALLOC calls and allocation sizes!
  96. */
  97. typedef void HUGE * (FAR DIAMONDAPI *PFNALLOC)(ULONG cb); /* pfna */
  98. #define FNALLOC(fn) void HUGE * FAR DIAMONDAPI fn(ULONG cb)
  99. typedef void (FAR DIAMONDAPI *PFNFREE)(void HUGE *pv); /* pfnf */
  100. #define FNFREE(fn) void FAR DIAMONDAPI fn(void HUGE *pv)
  101. /*** tcompXXX - Diamond compression types
  102. *
  103. * These are passed to FCIAddFile(), and are also stored in the CFFOLDER
  104. * structures in cabinet files.
  105. *
  106. * NOTE: We reserve bits for the TYPE, QUANTUM_LEVEL, and QUANTUM_MEM
  107. * to provide room for future expansion. Since this value is stored
  108. * in the CFDATA records in the cabinet file, we don't want to
  109. * have to change the format for existing compression configurations
  110. * if we add new ones in the future. This will allows us to read
  111. * old cabinet files in the future.
  112. */
  113. typedef unsigned short TCOMP; /* tcomp */
  114. #define tcompMASK_TYPE 0x000F // Mask for compression type
  115. #define tcompTYPE_NONE 0x0000 // No compression
  116. #define tcompTYPE_MSZIP 0x0001 // MSZIP
  117. #define tcompTYPE_QUANTUM 0x0002 // Quantum
  118. #define tcompBAD 0x000F // Unspecified compression type
  119. #define tcompMASK_QUANTUM_LEVEL 0x00F0 // Mask for Quantum Compression Level
  120. #define tcompQUANTUM_LEVEL_LO 0x0010 // Lowest Quantum Level (1)
  121. #define tcompQUANTUM_LEVEL_HI 0x0070 // Highest Quantum Level (7)
  122. #define tcompSHIFT_QUANTUM_LEVEL 4 // Amount to shift over to get int
  123. #define tcompMASK_QUANTUM_MEM 0x1F00 // Mask for Quantum Compression Memory
  124. #define tcompQUANTUM_MEM_LO 0x0A00 // Lowest Quantum Memory (10)
  125. #define tcompQUANTUM_MEM_HI 0x1500 // Highest Quantum Memory (21)
  126. #define tcompSHIFT_QUANTUM_MEM 8 // Amount to shift over to get int
  127. #define tcompMASK_RESERVED 0xE000 // Reserved bits (high 3 bits)
  128. #define CompressionTypeFromTCOMP(tc) \
  129. ((tc) & tcompMASK_TYPE)
  130. #define CompressionLevelFromTCOMP(tc) \
  131. (((tc) & tcompMASK_QUANTUM_LEVEL) >> tcompSHIFT_QUANTUM_LEVEL)
  132. #define CompressionMemoryFromTCOMP(tc) \
  133. (((tc) & tcompMASK_QUANTUM_MEM) >> tcompSHIFT_QUANTUM_MEM)
  134. #define TCOMPfromTypeLevelMemory(t,l,m) \
  135. (((m) << tcompSHIFT_QUANTUM_MEM ) | \
  136. ((l) << tcompSHIFT_QUANTUM_LEVEL) | \
  137. ( t ))
  138. //** Revert to default structure packing
  139. #if !defined(unix) && !defined(_WIN64)
  140. #pragma pack()
  141. #endif /* !defined(unix) && !defined(_WIN64) */
  142. #endif // !INCLUDED_TYPES_FCI_FDI
  143. /*** fdi_int.h - Diamond File Decompression Interface definitions
  144. *
  145. * Microsoft Confidential
  146. * Copyright (C) Microsoft Corporation 1993-1994
  147. * All Rights Reserved.
  148. *
  149. * Author:
  150. * Chuck Strouss, Benjamin W. Slivka
  151. *
  152. * History:
  153. * 30-Nov-1993 chuckst Created
  154. * 21-Dec-1993 bens Updated with comments from 12/21/93 design review
  155. * 09-Mar-1994 bens Add new error code
  156. * 17-Mar-1994 bens Specify structure packing explicitly
  157. * 21-Mar-1994 bens Spruce up comments
  158. * 25-Mar-1994 bens Add fdintCABINET_INFO notification
  159. * 31-Mar-1994 bens Clarify handling of open files when errors occur
  160. * 01-Apr-1994 bens Add FDIIsCabinet() function.
  161. * 07-Apr-1994 bens Add Decryption interfaces; remove fdintPROGRESS
  162. * 11-Apr-1994 bens Add more guidance on how to respond to FDI errors.
  163. * 13-Apr-1994 bens Add date & time & attribs to fdintCOPY_FILE
  164. * 18-Apr-1994 bens Changed CDECL to DIAMONDAPI
  165. * 05-May-1994 bens Clarified error handling (billhu/alanr/migueldc)
  166. * 11-May-1994 bens Added setId/iCabinet to fdintNEXT_CABINET
  167. * 07-Jul-1994 bens Support Quantum virtual file -- PLEASE note the
  168. * comments about PFNOPEN/PFNCLOSE changes, and
  169. * about reserving memory, if necessary, before
  170. * calling FDICreate()!
  171. * 19-Aug-1994 bens Add cpuType parameter to FDICreate().
  172. * 03-Apr-1995 jeffwe Added chaining indicators to FDICABINETINFO
  173. *
  174. *
  175. * ATTENTION:
  176. * This is the only documentation on the Diamond File Decompression
  177. * Interface (FDI). Please read it carefully, as there are some subtle
  178. * points in FDI that are carefully explained below.
  179. *
  180. * Concepts:
  181. * A *cabinet* file contains one or more *folders*. A folder contains
  182. * one or more (pieces of) *files*. A folder is by definition a
  183. * decompression unit, i.e., to extract a file from a folder, all of
  184. * the data from the start of the folder up through and including the
  185. * desired file must be read and decompressed.
  186. *
  187. * A folder can span one (or more) cabinet boundaries, and by implication
  188. * a file can also span one (or more) cabinet boundaries. Indeed, more
  189. * than one file can span a cabinet boundary, since Diamond concatenates
  190. * files together into a single data stream before compressing (actually,
  191. * at most one file will span any one cabinet boundary, but Diamond does
  192. * not know which file this is, since the mapping from uncompressed bytes
  193. * to compressed bytes is pretty obscure. Also, since Diamond compresses
  194. * in blocks of 32K (at present), any files with data in a 32K block that
  195. * spans a cabinet boundary require Diamond to read both cabinet files
  196. * to get the two halves of the compressed block).
  197. *
  198. * Overview:
  199. * The File Decompression Interface is used to simplify the reading of
  200. * Diamond cabinet files. A setup program will proceed in a manner very
  201. * similar to the pseudo code below. An FDI context is created, the
  202. * setup program calls FDICopy() for each cabinet to be processed. For
  203. * each file in the cabinet, FDICopy() calls a notification callback
  204. * routine, asking the setup program if the file should be copied.
  205. * This call-back approach is great because it allows the cabinet file
  206. * to be read and decompressed in an optimal manner, and also makes FDI
  207. * independent of the run-time environment -- FDI makes *no* C run-time
  208. * calls whatsoever. All memory allocation and file I/O functions are
  209. * passed into FDI by the client.
  210. *
  211. * main(...)
  212. * {
  213. * // Read INF file to construct list of desired files.
  214. * // Ideally, these would be sorted in the same order as the
  215. * // files appear in the cabinets, so that you can just walk
  216. * // down the list in response to fdintCOPY_FILE notifications.
  217. *
  218. * // Construct list of required cabinets.
  219. *
  220. * hfdi = FDICreate(...); // Create FDI context
  221. * For (cabinet in List of Cabinets) {
  222. * FDICopy(hfdi,cabinet,fdiNotify,...); // Process each cabinet
  223. * }
  224. * FDIDestroy(hfdi);
  225. * ...
  226. * }
  227. *
  228. * // Notification callback function
  229. * fdiNotify(fdint,...)
  230. * {
  231. * If (User Aborted) // Permit cancellation
  232. * if (fdint == fdintCLOSE_FILE_INFO)
  233. * close open file
  234. * return -1;
  235. * switch (fdint) {
  236. * case fdintCOPY_FILE: // File to copy, maybe
  237. * // Check file against list of desired files
  238. * if want to copy file
  239. * open destination file and return handle
  240. * else
  241. * return NULL; // Skip file
  242. * case fdintCLOSE_FILE_INFO:
  243. * close file
  244. * set date, time, and attributes
  245. *
  246. * case fdintNEXT_CABINET:
  247. * if not an error callback
  248. * Tell FDI to use suggested directory name
  249. * else
  250. * Tell user what the problem was, and prompt
  251. * for a new disk and/or path.
  252. * if user aborts
  253. * Tell FDI to abort
  254. * else
  255. * return to FDI to try another cabinet
  256. * //NOTE: Be sure to see the (sample) code in EXTRACT.C
  257. * // for an example of how to do this!
  258. * ...
  259. * }
  260. *
  261. * Error Handling Suggestions:
  262. * Since you the client have passed in *all* of the functions that
  263. * FDI uses to interact with the "outside" world, you are in prime
  264. * position to understand and deal with errors.
  265. *
  266. * The general philosophy of FDI is to pass all errors back up to
  267. * the client. FDI returns fairly generic error codes in the case
  268. * where one of the callback functions (PFNOPEN, PFNREAD, etc.) fail,
  269. * since it assumes that the callback function will save enough
  270. * information in a static/global so that when FDICopy() returns
  271. * fail, the client can examine this information and report enough
  272. * detail about the problem that the user can take corrective action.
  273. *
  274. * For very specific errors (CORRUPT_CABINET, for example), FDI returns
  275. * very specific error codes.
  276. *
  277. * THE BEST POLICY IS FOR YOUR CALLBACK ROUTINES TO AVOID RETURNING
  278. * ERRORS TO FDI!
  279. *
  280. * Examples:
  281. * (1) If the disk is getting full, instead of returning an error
  282. * from your PFNWRITE function, you should -- inside your
  283. * PFNWRITE function -- put up a dialog telling the user to free
  284. * some disk space.
  285. * (2) When you get the fdintNEXT_CABINET notification, you should
  286. * verify that the cabinet you return is the correct one (call
  287. * FDIIsCabinet(), and make sure the setID matches the one for
  288. * the current cabinet specified in the fdintCABINET_INFO, and
  289. * that the disk number is one greater.
  290. *
  291. * NOTE: FDI will continue to call fdintNEXT_CABINET until it
  292. * gets the cabinet it wants, or until you return -1
  293. * to abort the FDICopy() call.
  294. *
  295. * The documentation below on the FDI error codes provides explicit
  296. * guidance on how to avoid each error.
  297. *
  298. * If you find you must return a failure to FDI from one of your
  299. * callback functions, then FDICopy() frees all resources it allocated
  300. * and closes all files. If you can figure out how to overcome the
  301. * problem, you can call FDICopy() again on the last cabinet, and
  302. * skip any files that you already copied. But, note that FDI does
  303. * *not* maintain any state between FDICopy() calls, other than possibly
  304. * memory allocated for the decompressor.
  305. *
  306. * See FDIERROR for details on FDI error codes and recommended actions.
  307. *
  308. *
  309. * Progress Indicator Suggestions:
  310. * As above, all of the file I/O functions are supplied by you. So,
  311. * updating a progress indicator is very simple. You keep track of
  312. * the target files handles you have opened, along with the uncompressed
  313. * size of the target file. When you see writes to the handle of a
  314. * target file, you use the write count to update your status!
  315. * Since this method is available, there is no separate callback from
  316. * FDI just for progess indication.
  317. */
  318. #ifndef INCLUDED_FDI
  319. #define INCLUDED_FDI 1
  320. //** Specify structure packing explicitly for clients of FDI
  321. #if !defined(unix) && !defined(_WIN64)
  322. #pragma pack(4)
  323. #endif /* !defined(unix) && !defined(_WIN64) */
  324. /*** FDIERROR - Error codes returned in erf.erfOper field
  325. *
  326. * In general, FDI will only fail if one of the passed in memory or
  327. * file I/O functions fails. Other errors are pretty unlikely, and are
  328. * caused by corrupted cabinet files, passing in a file which is not a
  329. * cabinet file, or cabinet files out of order.
  330. *
  331. * Description: Summary of error.
  332. * Cause: List of possible causes of this error.
  333. * Response: How client might respond to this error, or avoid it in
  334. * the first place.
  335. */
  336. typedef enum {
  337. FDIERROR_NONE,
  338. // Description: No error
  339. // Cause: Function was successfull.
  340. // Response: Keep going!
  341. FDIERROR_CABINET_NOT_FOUND,
  342. // Description: Cabinet not found
  343. // Cause: Bad file name or path passed to FDICopy(), or returned
  344. // to fdintNEXT_CABINET.
  345. // Response: To prevent this error, validate the existence of the
  346. // the cabinet *before* passing the path to FDI.
  347. FDIERROR_NOT_A_CABINET,
  348. // Description: Cabinet file does not have the correct format
  349. // Cause: File passed to to FDICopy(), or returned to
  350. // fdintNEXT_CABINET, is too small to be a cabinet file,
  351. // or does not have the cabinet signature in its first
  352. // four bytes.
  353. // Response: To prevent this error, call FDIIsCabinet() to check a
  354. // cabinet before calling FDICopy() or returning the
  355. // cabinet path to fdintNEXT_CABINET.
  356. FDIERROR_UNKNOWN_CABINET_VERSION,
  357. // Description: Cabinet file has an unknown version number.
  358. // Cause: File passed to to FDICopy(), or returned to
  359. // fdintNEXT_CABINET, has what looks like a cabinet file
  360. // header, but the version of the cabinet file format
  361. // is not one understood by this version of FDI. The
  362. // erf.erfType field is filled in with the version number
  363. // found in the cabinet file.
  364. // Response: To prevent this error, call FDIIsCabinet() to check a
  365. // cabinet before calling FDICopy() or returning the
  366. // cabinet path to fdintNEXT_CABINET.
  367. FDIERROR_CORRUPT_CABINET,
  368. // Description: Cabinet file is corrupt
  369. // Cause: FDI returns this error any time it finds a problem
  370. // with the logical format of a cabinet file, and any
  371. // time one of the passed-in file I/O calls fails when
  372. // operating on a cabinet (PFNOPEN, PFNSEEK, PFNREAD,
  373. // or PFNCLOSE). The client can distinguish these two
  374. // cases based upon whether the last file I/O call
  375. // failed or not.
  376. // Response: Assuming this is not a real corruption problem in
  377. // a cabinet file, the file I/O functions could attempt
  378. // to do retries on failure (for example, if there is a
  379. // temporary network connection problem). If this does
  380. // not work, and the file I/O call has to fail, then the
  381. // FDI client will have to clean up and call the
  382. // FDICopy() function again.
  383. FDIERROR_ALLOC_FAIL,
  384. // Description: Could not allocate enough memory
  385. // Cause: FDI tried to allocate memory with the PFNALLOC
  386. // function, but it failed.
  387. // Response: If possible, PFNALLOC should take whatever steps
  388. // are possible to allocate the memory requested. If
  389. // memory is not immediately available, it might post a
  390. // dialog asking the user to free memory, for example.
  391. // Note that the bulk of FDI's memory allocations are
  392. // made at FDICreate() time and when the first cabinet
  393. // file is opened during FDICopy().
  394. FDIERROR_BAD_COMPR_TYPE,
  395. // Description: Unknown compression type in a cabinet folder
  396. // Cause: [Should never happen.] A folder in a cabinet has an
  397. // unknown compression type. This is probably caused by
  398. // a mismatch between the version of Diamond used to
  399. // create the cabinet and the FDI. LIB used to read the
  400. // cabinet.
  401. // Response: Abort.
  402. FDIERROR_MDI_FAIL,
  403. // Description: Failure decompressing data from a cabinet file
  404. // Cause: The decompressor found an error in the data coming
  405. // from the file cabinet. The cabinet file was corrupted.
  406. // [11-Apr-1994 bens When checksuming is turned on, this
  407. // error should never occur.]
  408. // Response: Probably should abort; only other choice is to cleanup
  409. // and call FDICopy() again, and hope there was some
  410. // intermittent data error that will not reoccur.
  411. FDIERROR_TARGET_FILE,
  412. // Description: Failure writing to target file
  413. // Cause: FDI returns this error any time it gets an error back
  414. // from one of the passed-in file I/O calls fails when
  415. // writing to a file being extracted from a cabinet.
  416. // Response: To avoid or minimize this error, the file I/O functions
  417. // could attempt to avoid failing. A common cause might
  418. // be disk full -- in this case, the PFNWRITE function
  419. // could have a check for free space, and put up a dialog
  420. // asking the user to free some disk space.
  421. FDIERROR_RESERVE_MISMATCH,
  422. // Description: Cabinets in a set do not have the same RESERVE sizes
  423. // Cause: [Should never happen]. FDI requires that the sizes of
  424. // the per-cabinet, per-folder, and per-data block
  425. // RESERVE sections be consistent across all the cabinet
  426. // in a set. Diamond will only generate cabinet sets
  427. // with these properties.
  428. // Response: Abort.
  429. FDIERROR_WRONG_CABINET,
  430. // Description: Cabinet returned on fdintNEXT_CABINET is incorrect
  431. // Cause: NOTE: THIS ERROR IS NEVER RETURNED BY FDICopy()!
  432. // Rather, FDICopy() keeps calling the fdintNEXT_CABINET
  433. // callback until either the correct cabinet is specified,
  434. // or you return ABORT.
  435. // When FDICopy() is extracting a file that crosses a
  436. // cabinet boundary, it calls fdintNEXT_CABINET to ask
  437. // for the path to the next cabinet. Not being very
  438. // trusting, FDI then checks to make sure that the
  439. // correct continuation cabinet was supplied! It does
  440. // this by checking the "setID" and "iCabinet" fields
  441. // in the cabinet. When DIAMOND.EXE creates a set of
  442. // cabinets, it constructs the "setID" using the sum
  443. // of the bytes of all the destination file names in
  444. // the cabinet set. FDI makes sure that the 16-bit
  445. // setID of the continuation cabinet matches the
  446. // cabinet file just processed. FDI then checks that
  447. // the cabinet number (iCabinet) is one more than the
  448. // cabinet number for the cabinet just processed.
  449. // Response: You need code in your fdintNEXT_CABINET (see below)
  450. // handler to do retries if you get recalled with this
  451. // error. See the sample code (EXTRACT.C) to see how
  452. // this should be handled.
  453. FDIERROR_USER_ABORT
  454. // Description: FDI aborted.
  455. // Cause: An FDI callback returnd -1 (usually).
  456. // Response: Up to client.
  457. } FDIERROR;
  458. /*** HFDI - Handle to an FDI context
  459. *
  460. * FDICreate() creates this, and it must be passed to all other FDI
  461. * functions.
  462. */
  463. typedef void FAR *HFDI; /* hfdi */
  464. /*** FDICABINETINFO - Information about a cabinet
  465. *
  466. */
  467. typedef struct {
  468. long cbCabinet; // Total length of cabinet file
  469. USHORT cFolders; // Count of folders in cabinet
  470. USHORT cFiles; // Count of files in cabinet
  471. USHORT setID; // Cabinet set ID
  472. USHORT iCabinet; // Cabinet number in set (0 based)
  473. BOOL fReserve; // TRUE => RESERVE present in cabinet
  474. BOOL hasprev; // TRUE => Cabinet is chained prev
  475. BOOL hasnext; // TRUE => Cabinet is chained next
  476. } FDICABINETINFO; /* fdici */
  477. typedef FDICABINETINFO FAR *PFDICABINETINFO; /* pfdici */
  478. /*** FDIDECRYPTTYPE - PFNFDIDECRYPT command types
  479. *
  480. */
  481. typedef enum {
  482. fdidtNEW_CABINET, // New cabinet
  483. fdidtNEW_FOLDER, // New folder
  484. fdidtDECRYPT // Decrypt a data block
  485. } FDIDECRYPTTYPE; /* fdidt */
  486. /*** FDIDECRYPT - Data for PFNFDIDECRYPT function
  487. *
  488. */
  489. typedef struct {
  490. FDIDECRYPTTYPE fdidt; // Command type (selects union below)
  491. void FAR *pvUser; // Decryption context
  492. union {
  493. struct { // fdidtNEW_CABINET
  494. void FAR *pHeaderReserve; // RESERVE section from CFHEADER
  495. USHORT cbHeaderReserve; // Size of pHeaderReserve
  496. USHORT setID; // Cabinet set ID
  497. int iCabinet; // Cabinet number in set (0 based)
  498. } cabinet;
  499. struct { // fdidtNEW_FOLDER
  500. void FAR *pFolderReserve; // RESERVE section from CFFOLDER
  501. USHORT cbFolderReserve; // Size of pFolderReserve
  502. USHORT iFolder; // Folder number in cabinet (0 based)
  503. } folder;
  504. struct { // fdidtDECRYPT
  505. void FAR *pDataReserve; // RESERVE section from CFDATA
  506. USHORT cbDataReserve; // Size of pDataReserve
  507. void FAR *pbData; // Data buffer
  508. USHORT cbData; // Size of data buffer
  509. BOOL fSplit; // TRUE if this is a split data block
  510. USHORT cbPartial; // 0 if this is not a split block, or
  511. // the first piece of a split block;
  512. // Greater than 0 if this is the
  513. // second piece of a split block.
  514. } decrypt;
  515. }
  516. #ifdef unix
  517. MWUNION_TAG
  518. #endif /* unix */
  519. ;
  520. } FDIDECRYPT; /* fdid */
  521. typedef FDIDECRYPT FAR *PFDIDECRYPT; /* pfdid */
  522. /*** PFNFDIDECRYPT - FDI Decryption callback
  523. *
  524. * If this function is passed on the FDICopy() call, then FDI calls it
  525. * at various times to update the decryption state and to decrypt FCDATA
  526. * blocks.
  527. *
  528. * Common Entry Conditions:
  529. * pfdid->fdidt - Command type
  530. * pfdid->pvUser - pvUser value from FDICopy() call
  531. *
  532. * fdidtNEW_CABINET: //** Notification of a new cabinet
  533. * Entry:
  534. * pfdid->cabinet.
  535. * pHeaderReserve - RESERVE section from CFHEADER
  536. * cbHeaderReserve - Size of pHeaderReserve
  537. * setID - Cabinet set ID
  538. * iCabinet - Cabinet number in set (0 based)
  539. * Exit-Success:
  540. * returns anything but -1;
  541. * Exit-Failure:
  542. * returns -1; FDICopy() is aborted.
  543. * Notes:
  544. * (1) This call allows the decryption code to pick out any information
  545. * from the cabinet header reserved area (placed there by DIACRYPT)
  546. * needed to perform decryption. If there is no such information,
  547. * this call would presumably be ignored.
  548. * (2) This call is made very soon after fdintCABINET_INFO.
  549. *
  550. * fdidtNEW_FOLDER: //** Notification of a new folder
  551. * Entry:
  552. * pfdid->folder.
  553. * pFolderReserve - RESERVE section from CFFOLDER
  554. * cbFolderReserve - Size of pFolderReserve
  555. * iFolder - Folder number in cabinet (0 based)
  556. * Exit-Success:
  557. * returns anything but -1;
  558. * Exit-Failure:
  559. * returns -1; FDICopy() is aborted.
  560. * Notes:
  561. * This call allows the decryption code to pick out any information
  562. * from the folder reserved area (placed there by DIACRYPT) needed
  563. * to perform decryption. If there is no such information, this
  564. * call would presumably be ignored.
  565. *
  566. * fdidtDECRYPT: //** Decrypt a data buffer
  567. * Entry:
  568. * pfdid->folder.
  569. * pDataReserve - RESERVE section for this CFDATA block
  570. * cbDataReserve - Size of pDataReserve
  571. * pbData - Data buffer
  572. * cbData - Size of data buffer
  573. * fSplit - TRUE if this is a split data block
  574. * cbPartial - 0 if this is not a split block, or the first
  575. * piece of a split block; Greater than 0 if
  576. * this is the second piece of a split block.
  577. * Exit-Success:
  578. * returns TRUE;
  579. * Exit-Failure:
  580. * returns FALSE; error during decrypt
  581. * returns -1; FDICopy() is aborted.
  582. * Notes:
  583. * Diamond will split CFDATA blocks across cabinet boundaries if
  584. * necessary. To provide maximum flexibility, FDI will call the
  585. * fdidtDECRYPT function twice on such split blocks, once when
  586. * the first portion is read, and again when the second portion
  587. * is read. And, of course, most data blocks will not be split.
  588. * So, there are three cases:
  589. *
  590. * 1) fSplit == FALSE
  591. * You have the entire data block, so decrypt it.
  592. *
  593. * 2) fSplit == TRUE, cbPartial == 0
  594. * This is the first portion of a split data block, so cbData
  595. * is the size of this portion. You can either choose to decrypt
  596. * this piece, or ignore this call and decrypt the full CFDATA
  597. * block on the next (second) fdidtDECRYPT call.
  598. *
  599. * 3) fSplit == TRUE, cbPartial > 0
  600. * This is the second portion of a split data block (indeed,
  601. * cbPartial will have the same value as cbData did on the
  602. * immediately preceeding fdidtDECRYPT call!). If you decrypted
  603. * the first portion on the first call, then you can decrypt the
  604. * second portion now. If you ignored the first call, then you
  605. * can decrypt the entire buffer.
  606. * NOTE: pbData points to the second portion of the split data
  607. * block in this case, *not* the entire data block. If
  608. * you want to wait until the second piece to decrypt the
  609. * *entire* block, pbData-cbPartial is the address of the
  610. * start of the whole block, and cbData+cbPartial is its
  611. * size.
  612. */
  613. typedef int (FAR DIAMONDAPI *PFNFDIDECRYPT)(PFDIDECRYPT pfdid); /* pfnfdid */
  614. #define FNFDIDECRYPT(fn) int FAR DIAMONDAPI fn(PFDIDECRYPT pfdid)
  615. /*** FDINOTIFICATION - Notification structure for PFNFDINOTIFY
  616. *
  617. * See the FDINOTIFICATIONTYPE definition for information on usage and
  618. * meaning of these fields.
  619. */
  620. typedef struct {
  621. // long fields
  622. long cb;
  623. char FAR *psz1;
  624. char FAR *psz2;
  625. char FAR *psz3; // Points to a 256 character buffer
  626. void FAR *pv; // Value for client
  627. // int fields
  628. INT_PTR hf;
  629. // short fields
  630. USHORT date;
  631. USHORT time;
  632. USHORT attribs;
  633. USHORT setID; // Cabinet set ID
  634. USHORT iCabinet; // Cabinet number (0-based)
  635. FDIERROR fdie;
  636. } FDINOTIFICATION, FAR *PFDINOTIFICATION; /* fdin, pfdin */
  637. /*** FDINOTIFICATIONTYPE - FDICopy notification types
  638. *
  639. * The notification function for FDICopy can be called with the following
  640. * values for the fdint parameter. In all cases, the pfdin->pv field is
  641. * filled in with the value of the pvUser argument passed in to FDICopy().
  642. *
  643. * A typical sequence of calls will be something like this:
  644. * fdintCABINET_INFO // Info about the cabinet
  645. * fdintPARTIAL_FILE // Only if this is not the first cabinet, and
  646. * // one or more files were continued from the
  647. * // previous cabinet.
  648. * ...
  649. * fdintPARTIAL_FILE
  650. * fdintCOPY_FILE // The first file that starts in this cabinet
  651. * ...
  652. * fdintCOPY_FILE // Now let's assume you want this file...
  653. * // PFNWRITE called multiple times to write to this file.
  654. * fdintCLOSE_FILE_INFO // File done, set date/time/attributes
  655. *
  656. * fdintCOPY_FILE // Now let's assume you want this file...
  657. * // PFNWRITE called multiple times to write to this file.
  658. * fdintNEXT_CABINET // File was continued to next cabinet!
  659. * fdintCABINET_INFO // Info about the new cabinet
  660. * // PFNWRITE called multiple times to write to this file.
  661. * fdintCLOSE_FILE_INFO // File done, set date/time/attributes
  662. * ...
  663. *
  664. * fdintCABINET_INFO:
  665. * Called exactly once for each cabinet opened by FDICopy(), including
  666. * continuation cabinets opened due to file(s) spanning cabinet
  667. * boundaries. Primarily intended to permit EXTRACT.EXE to
  668. * automatically select the next cabinet in a cabinet sequence even if
  669. * not copying files that span cabinet boundaries.
  670. * Entry:
  671. * pfdin->psz1 = name of next cabinet
  672. * pfdin->psz2 = name of next disk
  673. * pfdin->psz3 = cabinet path name
  674. * pfdin->setID = cabinet set ID (a random 16-bit number)
  675. * pfdin->iCabinet = Cabinet number within cabinet set (0-based)
  676. * Exit-Success:
  677. * Return anything but -1
  678. * Exit-Failure:
  679. * Returns -1 => Abort FDICopy() call
  680. * Notes:
  681. * This call is made *every* time a new cabinet is examined by
  682. * FDICopy(). So if "foo2.cab" is examined because a file is
  683. * continued from "foo1.cab", and then you call FDICopy() again
  684. * on "foo2.cab", you will get *two* fdintCABINET_INFO calls all
  685. * told.
  686. *
  687. * fdintCOPY_FILE:
  688. * Called for each file that *starts* in the current cabinet, giving
  689. * the client the opportunity to request that the file be copied or
  690. * skipped.
  691. * Entry:
  692. * pfdin->psz1 = file name in cabinet
  693. * pfdin->cb = uncompressed size of file
  694. * pfdin->date = file date
  695. * pfdin->time = file time
  696. * pfdin->attribs = file attributes
  697. * Exit-Success:
  698. * Return non-zero file handle for destination file; FDI writes
  699. * data to this file use the PFNWRITE function supplied to FDICreate,
  700. * and then calls fdintCLOSE_FILE_INFO to close the file and set
  701. * the date, time, and attributes. NOTE: This file handle returned
  702. * must also be closeable by the PFNCLOSE function supplied to
  703. * FDICreate, since if an error occurs while writing to this handle,
  704. * FDI will use the PFNCLOSE function to close the file so that the
  705. * client may delete it.
  706. * Exit-Failure:
  707. * Returns 0 => Skip file, do not copy
  708. * Returns -1 => Abort FDICopy() call
  709. *
  710. * fdintCLOSE_FILE_INFO:
  711. * Called after all of the data has been written to a target file.
  712. * This function must close the file and set the file date, time,
  713. * and attributes.
  714. * Entry:
  715. * pfdin->psz1 = file name in cabinet
  716. * pfdin->hf = file handle
  717. * pfdin->date = file date
  718. * pfdin->time = file time
  719. * pfdin->attribs = file attributes
  720. * Exit-Success:
  721. * Returns TRUE
  722. * Exit-Failure:
  723. * Returns FALSE, or -1 to abort;
  724. * IMPORTANT NOTE:
  725. * FDI assumes that the target file was closed, even if this
  726. * callback returns failure. FDI will NOT attempt to use
  727. * the PFNCLOSE function supplied on FDICreate() to close
  728. * the file!
  729. *
  730. * fdintPARTIAL_FILE:
  731. * Called for files at the front of the cabinet that are CONTINUED
  732. * from a previous cabinet. This callback occurs only when FDICopy is
  733. * started on second or subsequent cabinet in a series that has files
  734. * continued from a previous cabinet.
  735. * Entry:
  736. * pfdin->psz1 = file name of file CONTINUED from a PREVIOUS cabinet
  737. * pfdin->psz2 = name of cabinet where file starts
  738. * pfdin->psz3 = name of disk where file starts
  739. * Exit-Success:
  740. * Return anything other than -1; enumeration continues
  741. * Exit-Failure:
  742. * Returns -1 => Abort FDICopy() call
  743. *
  744. * fdintNEXT_CABINET:
  745. * This function is *only* called when fdintCOPY_FILE was told to copy
  746. * a file in the current cabinet that is continued to a subsequent
  747. * cabinet file. It is important that the cabinet path name (psz3)
  748. * be validated before returning! This function should ensure that
  749. * the cabinet exists and is readable before returning. So, this
  750. * is the function that should, for example, issue a disk change
  751. * prompt and make sure the cabinet file exists.
  752. *
  753. * When this function returns to FDI, FDI will check that the setID
  754. * and iCabinet match the expected values for the next cabinet.
  755. * If not, FDI will continue to call this function until the correct
  756. * cabinet file is specified, or until this function returns -1 to
  757. * abort the FDICopy() function. pfdin->fdie is set to
  758. * FDIERROR_WRONG_CABINET to indicate this case.
  759. *
  760. * If you *haven't* ensured that the cabinet file is present and
  761. * readable, or the cabinet file has been damaged, pfdin->fdie will
  762. * receive other appropriate error codes:
  763. *
  764. * FDIERROR_CABINET_NOT_FOUND
  765. * FDIERROR_NOT_A_CABINET
  766. * FDIERROR_UNKNOWN_CABINET_VERSION
  767. * FDIERROR_CORRUPT_CABINET
  768. * FDIERROR_BAD_COMPR_TYPE
  769. * FDIERROR_RESERVE_MISMATCH
  770. * FDIERROR_WRONG_CABINET
  771. *
  772. * Entry:
  773. * pfdin->psz1 = name of next cabinet where current file is continued
  774. * pfdin->psz2 = name of next disk where current file is continued
  775. * pfdin->psz3 = cabinet path name; FDI concatenates psz3 with psz1
  776. * to produce the fully-qualified path for the cabinet
  777. * file. The 256-byte buffer pointed at by psz3 may
  778. * be modified, but psz1 may not!
  779. * pfdin->fdie = FDIERROR_WRONG_CABINET if the previous call to
  780. * fdintNEXT_CABINET specified a cabinet file that
  781. * did not match the setID/iCabinet that was expected.
  782. * Exit-Success:
  783. * Return anything but -1
  784. * Exit-Failure:
  785. * Returns -1 => Abort FDICopy() call
  786. * Notes:
  787. * This call is almost always made when a target file is open and
  788. * being written to, and the next cabinet is needed to get more
  789. * data for the file.
  790. */
  791. typedef enum {
  792. fdintCABINET_INFO, // General information about cabinet
  793. fdintPARTIAL_FILE, // First file in cabinet is continuation
  794. fdintCOPY_FILE, // File to be copied
  795. fdintCLOSE_FILE_INFO, // close the file, set relevant info
  796. fdintNEXT_CABINET // File continued to next cabinet
  797. } FDINOTIFICATIONTYPE; /* fdint */
  798. typedef INT_PTR (FAR DIAMONDAPI *PFNFDINOTIFY)(FDINOTIFICATIONTYPE fdint,
  799. PFDINOTIFICATION pfdin); /* pfnfdin */
  800. #define FNFDINOTIFY(fn) INT_PTR FAR DIAMONDAPI fn(FDINOTIFICATIONTYPE fdint, \
  801. PFDINOTIFICATION pfdin)
  802. /*** PFNOPEN - File I/O callbacks for FDI
  803. * PFNREAD
  804. * PFNWRITE
  805. * PFNCLOSE
  806. * PFNSEEK
  807. *
  808. * These are modeled after the C run-time routines _open, _read,
  809. * _write, _close, and _lseek. The values for the PFNOPEN oflag
  810. * and pmode calls are those defined for _open. FDI expects error
  811. * handling to be identical to these C run-time routines.
  812. *
  813. * As long as you faithfully copy these aspects, you can supply
  814. * any functions you like!
  815. *
  816. *
  817. * SPECIAL NOTE FOR QUANTUM DECOMPRESSION:
  818. * When using Quantum compression, at compress time (with Diamond)
  819. * you specify how much memory Quantum requires at *decompress* time
  820. * to store the decompression history buffer. This can be as large
  821. * as *2Mb*, and in an MS-DOS environment, for example, this much
  822. * memory may not be available (certainly not under 640K!). To permit
  823. * large CompressionMemory settings on any machine, the Quantum
  824. * decompressor will attempt to create a "spill file" if there is not
  825. * sufficient memory available.
  826. *
  827. * For PFNOPEN, a special pszFile parameter is passed to indicate that
  828. * a temporary "spill file" is requested. The name passed is "*", and
  829. * you should cast the pszFile parameter to an FDISPILLFILE pointer,
  830. * and get the requested file size. You then need to create a file
  831. * of the specified size with read/write access, save the file name and
  832. * handle for later use by PFNCLOSE, and then return the handle. If
  833. * you cannot create the file of the specified size, you should return
  834. * an error (-1). This file should be placed on a fast local hard disk,
  835. * to maximize the speed of decompression.
  836. *
  837. * For PFNCLOSE, you should check the handle to see if it the spill file
  838. * created previously by PFNOPEN (FDI will create at most one spill file
  839. * per FDICreate() call). If it is the spill file handle, you should
  840. * close the handle and then delete the file, using the file name you
  841. * saved when you created the spill file in PFNOPEN.
  842. *
  843. * WARNING: You should never assume you know what file is being
  844. * opened at any one point in time! FDI will usually
  845. * stick to opening cabinet files, but it is possible
  846. * that in a future implementation it may open temporary
  847. * files or open cabinet files in a different order.
  848. *
  849. * Notes for Memory Mapped File fans:
  850. * You can write wrapper routines to allow FDI to work on memory
  851. * mapped files. You'll have to create your own "handle" type so that
  852. * you can store the base memory address of the file and the current
  853. * seek position, and then you'll allocate and fill in one of these
  854. * structures and return a pointer to it in response to the PFNOPEN
  855. * call and the fdintCOPY_FILE call. Your PFNREAD and PFNWRITE
  856. * functions will do memcopy(), and update the seek position in your
  857. * "handle" structure. PFNSEEK will just change the seek position
  858. * in your "handle" structure.
  859. */
  860. typedef int (FAR DIAMONDAPI *PFNOPEN) (char FAR *pszFile, int oflag, int pmode);
  861. typedef UINT (FAR DIAMONDAPI *PFNREAD) (INT_PTR hf, void FAR *pv, UINT cb);
  862. typedef UINT (FAR DIAMONDAPI *PFNWRITE)(INT_PTR hf, void FAR *pv, UINT cb);
  863. typedef int (FAR DIAMONDAPI *PFNCLOSE)(INT_PTR hf);
  864. typedef long (FAR DIAMONDAPI *PFNSEEK) (INT_PTR hf, long dist, int seektype);
  865. #if !defined(unix) && !defined(_WIN64)
  866. #pragma pack(1)
  867. #endif /* !defined(unix) && !defined(_WIN64) */
  868. /** FDISPILLFILE - Pass as pszFile on PFNOPEN to create spill file
  869. *
  870. * ach - A two byte string to signal to PFNOPEN that a spill file is
  871. * requested. Value is '*','\0'.
  872. * cbFile - Required spill file size, in bytes.
  873. */
  874. typedef struct {
  875. char ach[2]; // Set to { '*', '\0' }
  876. long cbFile; // Required spill file size
  877. } FDISPILLFILE; /* fdisf */
  878. typedef FDISPILLFILE *PFDISPILLFILE; /* pfdisf */
  879. #if !defined(unix) && !defined(_WIN64)
  880. #pragma pack()
  881. #endif /* !defined(unix) && !defined(_WIN64) */
  882. /*** cpuType values for FDICreate()
  883. *
  884. * WARNING: For 16-bit Windows applications, the CPU detection may not
  885. * correctly detect 286 CPUs. Instead, use the following code:
  886. *
  887. * DWORD flags;
  888. * int cpuType;
  889. *
  890. * flags = GetWinFlags();
  891. * if (flags & WF_CPU286)
  892. * cpuType = cpu80286;
  893. * else
  894. * cpuType = cpu80386;
  895. *
  896. * hfdi = FDICreate(....,cpuType,...);
  897. */
  898. #define cpuUNKNOWN (-1) /* FDI does detection */
  899. #define cpu80286 (0) /* '286 opcodes only */
  900. #define cpu80386 (1) /* '386 opcodes used */
  901. /*** FDICreate - Create an FDI context
  902. *
  903. * Entry:
  904. * pfnalloc
  905. * pfnfree
  906. * pfnopen
  907. * pfnread
  908. * pfnwrite
  909. * pfnclose
  910. * pfnlseek
  911. * cpuType - Select CPU type (auto-detect, 286, or 386+)
  912. * WARNING: Don't use auto-detect from a 16-bit Windows
  913. * application! Use GetWinFlags()!
  914. * NOTE: For the 32-bit FDI.LIB, this parameter is ignored!
  915. * perf
  916. *
  917. * Exit-Success:
  918. * Returns non-NULL FDI context handle.
  919. *
  920. * Exit-Failure:
  921. * Returns NULL; perf filled in with error code
  922. *
  923. * Special notes for Quantum Decompression:
  924. * If you have used a high setting for CompressionMemory in creating
  925. * the cabinet file(s), then FDI will attempt to allocate a lot of
  926. * memory (as much as 2Mb, if you specified 21 for CompressionMemory).
  927. * Therefore, if you plan to allocate additional memory *after* the
  928. * FDICreate() call, you should reserve some memory *prior* to calling
  929. * FDICreate(), and then free it up afterwards (or do all your allocation
  930. * before calling FDICreate().
  931. */
  932. HFDI FAR DIAMONDAPI FDICreate(PFNALLOC pfnalloc,
  933. PFNFREE pfnfree,
  934. PFNOPEN pfnopen,
  935. PFNREAD pfnread,
  936. PFNWRITE pfnwrite,
  937. PFNCLOSE pfnclose,
  938. PFNSEEK pfnseek,
  939. int cpuType,
  940. PERF perf);
  941. /*** FDIIsCabinet - Determines if file is a cabinet, returns info if it is
  942. *
  943. * Entry:
  944. * hfdi - Handle to FDI context (created by FDICreate())
  945. * hf - File handle suitable for PFNREAD/PFNSEEK, positioned
  946. * at offset 0 in the file to test.
  947. * pfdici - Buffer to receive info about cabinet if it is one.
  948. *
  949. * Exit-Success:
  950. * Returns TRUE; file is a cabinet, pfdici filled in.
  951. *
  952. * Exit-Failure:
  953. * Returns FALSE, file is not a cabinet; If an error occurred,
  954. * perf (passed on FDICreate call!) filled in with error.
  955. */
  956. BOOL FAR DIAMONDAPI FDIIsCabinet(HFDI hfdi,
  957. INT_PTR hf,
  958. PFDICABINETINFO pfdici);
  959. /*** FDICopy - extracts files from a cabinet
  960. *
  961. * Entry:
  962. * hfdi - handle to FDI context (created by FDICreate())
  963. * pszCabinet - main name of cabinet file
  964. * pszCabPath - Path to cabinet file(s)
  965. * flags - Flags to modify behavior
  966. * pfnfdin - Notification function
  967. * pfnfdid - Decryption function (pass NULL if not used)
  968. * pvUser - User specified value to pass to notification function
  969. *
  970. * Exit-Success:
  971. * Returns TRUE;
  972. *
  973. * Exit-Failure:
  974. * Returns FALSE, perf (passed on FDICreate call!) filled in with
  975. * error.
  976. *
  977. * Notes:
  978. * (1) If FDICopy() fails while a target file is being written out, then
  979. * FDI will use the PFNCLOSE function to close the file handle for that
  980. * target file that was returned from the fdintCOPY_FILE notification.
  981. * The client application is then free to delete the target file, since
  982. * it will not be in a valid state (since there was an error while
  983. * writing it out).
  984. */
  985. BOOL FAR DIAMONDAPI FDICopy(HFDI hfdi,
  986. char FAR *pszCabinet,
  987. char FAR *pszCabPath,
  988. int flags,
  989. PFNFDINOTIFY pfnfdin,
  990. PFNFDIDECRYPT pfnfdid,
  991. void FAR *pvUser);
  992. /*** FDIDestroy - Destroy an FDI context
  993. *
  994. * Entry:
  995. * hfdi - handle to FDI context (created by FDICreate())
  996. *
  997. * Exit-Success:
  998. * Returns TRUE;
  999. *
  1000. * Exit-Failure:
  1001. * Returns FALSE;
  1002. */
  1003. BOOL FAR DIAMONDAPI FDIDestroy(HFDI hfdi);
  1004. //** Revert to default structure packing
  1005. #if !defined(unix) && !defined(_WIN64)
  1006. #pragma pack()
  1007. #endif /* !defined(unix) && !defined(_WIN64) */
  1008. #endif //!INCLUDED_FDI