Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

592 lines
10 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. //#define MY_FDI_MEM_STATS
  4. HFDI FdiContext;
  5. ERF FdiError;
  6. LONG MyLastDiamondWriteError,MyLastDiamondIoError;
  7. INT_PTR CurrentTargetFileHandle;
  8. INT TicksForThisFile;
  9. DWORD CurrentTargetFileSize;
  10. PFNWFROMW GaugeTicker;
  11. extern HWND hwndFrame;
  12. #ifdef MY_FDI_MEM_STATS
  13. DWORD DiAllocCount,DiFreeCount;
  14. LONG DiCurrentAllocation,DiPeakAllocation;
  15. #endif
  16. INT_PTR
  17. DIAMONDAPI
  18. DiamondNotifyFunction(
  19. IN FDINOTIFICATIONTYPE Operation,
  20. IN PFDINOTIFICATION Parameters
  21. )
  22. {
  23. switch(Operation) {
  24. case fdintCABINET_INFO:
  25. case fdintNEXT_CABINET:
  26. case fdintPARTIAL_FILE:
  27. default:
  28. //
  29. // Cabinet management functions which we don't use.
  30. // Return success.
  31. //
  32. return(0);
  33. case fdintCOPY_FILE:
  34. //
  35. // Diamond is asking us whether we want to copy the file.
  36. // The name for the destination is stored as the
  37. // user parameter; open the file.
  38. //
  39. CurrentTargetFileSize = Parameters->cb;
  40. //
  41. // Target file handle is the user data value.
  42. //
  43. return((INT_PTR)Parameters->pv);
  44. case fdintCLOSE_FILE_INFO:
  45. //
  46. // Diamond is done with the target file and wants us to close it.
  47. // (ie, this is the counterpart to fdint_COPY_FILE).
  48. // However our target file open/close operations are controlled
  49. // in copy.c so we do nothing here.
  50. //
  51. //_lclose(Parameters->hf);
  52. return(TRUE);
  53. }
  54. }
  55. PVOID
  56. DIAMONDAPI
  57. SpdFdiAlloc(
  58. IN ULONG NumberOfBytes
  59. )
  60. /*++
  61. Routine Description:
  62. Callback used by FDICopy to allocate memory.
  63. Arguments:
  64. NumberOfBytes - supplies desired size of block.
  65. Return Value:
  66. Returns pointer to a block of memory or NULL
  67. if memory cannot be allocated.
  68. --*/
  69. {
  70. #ifdef MY_FDI_MEM_STATS
  71. PDWORD p;
  72. p = SAlloc(NumberOfBytes+sizeof(DWORD));
  73. if(p) {
  74. *p++ = NumberOfBytes;
  75. DiAllocCount++;
  76. DiCurrentAllocation += (LONG)NumberOfBytes;
  77. if(DiCurrentAllocation > DiPeakAllocation) {
  78. DiPeakAllocation = DiCurrentAllocation;
  79. }
  80. }
  81. return(p);
  82. #else
  83. return(SAlloc(NumberOfBytes));
  84. #endif
  85. }
  86. VOID
  87. DIAMONDAPI
  88. SpdFdiFree(
  89. IN PVOID Block
  90. )
  91. /*++
  92. Routine Description:
  93. Callback used by FDICopy to free a memory block.
  94. The block must have been allocated with SpdFdiAlloc().
  95. Arguments:
  96. Block - supplies pointer to block of memory to be freed.
  97. Return Value:
  98. None.
  99. --*/
  100. {
  101. #ifdef MY_FDI_MEM_STATS
  102. PDWORD p = (PDWORD)Block - 1;
  103. DiCurrentAllocation -= (LONG)*p;
  104. DiFreeCount++;
  105. SFree(p);
  106. #else
  107. SFree(Block);
  108. #endif
  109. }
  110. INT_PTR
  111. DIAMONDAPI
  112. SpdFdiOpen(
  113. IN PSTR FileName,
  114. IN int oflag,
  115. IN int pmode
  116. )
  117. /*++
  118. Routine Description:
  119. Callback used by FDICopy to open files.
  120. Arguments:
  121. FileName - supplies name of file to be opened.
  122. oflag - supplies flags for open.
  123. pmode - supplies additional flags for open.
  124. Return Value:
  125. Handle to open file or -1 if error occurs.
  126. --*/
  127. {
  128. HFILE h;
  129. int OpenMode;
  130. if(oflag & _O_WRONLY) {
  131. OpenMode = OF_WRITE;
  132. } else {
  133. if(oflag & _O_RDWR) {
  134. OpenMode = OF_READWRITE;
  135. } else {
  136. OpenMode = OF_READ;
  137. }
  138. }
  139. h = _lopen(FileName,OpenMode | OF_SHARE_DENY_WRITE);
  140. if(h == HFILE_ERROR) {
  141. //
  142. // Want to return an open error, but there is none.
  143. //
  144. MyLastDiamondIoError = rcReadError;
  145. return(-1);
  146. }
  147. return((INT_PTR)h);
  148. }
  149. UINT
  150. DIAMONDAPI
  151. SpdFdiRead(
  152. IN INT_PTR Handle,
  153. OUT PVOID pv,
  154. IN UINT ByteCount
  155. )
  156. /*++
  157. Routine Description:
  158. Callback used by FDICopy to read from a file.
  159. Arguments:
  160. Handle - supplies handle to open file to be read from.
  161. pv - supplies pointer to buffer to receive bytes we read.
  162. ByteCount - supplies number of bytes to read.
  163. Return Value:
  164. Number of bytes read (ByteCount) or -1 if an error occurs.
  165. --*/
  166. {
  167. UINT rc;
  168. FYield();
  169. if(fUserQuit) {
  170. rc = (UINT)(-1);
  171. } else {
  172. rc = _lread((HFILE)Handle,pv,ByteCount);
  173. if(rc == HFILE_ERROR) {
  174. rc = (UINT)(-1);
  175. MyLastDiamondIoError = rcReadError;
  176. }
  177. }
  178. FYield();
  179. return(rc);
  180. }
  181. UINT
  182. DIAMONDAPI
  183. SpdFdiWrite(
  184. IN INT_PTR Handle,
  185. IN PVOID pv,
  186. IN UINT ByteCount
  187. )
  188. /*++
  189. Routine Description:
  190. Callback used by FDICopy to write to a file.
  191. Arguments:
  192. Handle - supplies handle to open file to be written to.
  193. pv - supplies pointer to buffer containing bytes to write.
  194. ByteCount - supplies number of bytes to write.
  195. Return Value:
  196. Number of bytes written (ByteCount) or -1 if an error occurs.
  197. --*/
  198. {
  199. UINT rc;
  200. //
  201. // Assume failure.
  202. //
  203. rc = (UINT)(-1);
  204. FYield();
  205. if(!fUserQuit) {
  206. rc = _lwrite((HFILE)Handle,pv,ByteCount);
  207. if(rc == HFILE_ERROR) {
  208. MyLastDiamondIoError = (GetLastError() == ERROR_DISK_FULL) ? rcDiskFull : rcWriteError;
  209. MyLastDiamondWriteError = MyLastDiamondWriteError;
  210. } else {
  211. if(rc == ByteCount) {
  212. if((Handle == CurrentTargetFileHandle) && GaugeTicker) {
  213. //
  214. // Update gauge.
  215. //
  216. GaugeTicker(ByteCount * TicksForThisFile / CurrentTargetFileSize);
  217. }
  218. } else {
  219. MyLastDiamondIoError = rcDiskFull;
  220. MyLastDiamondWriteError = rcDiskFull;
  221. rc = (UINT)(-1);
  222. }
  223. }
  224. }
  225. FYield();
  226. return(rc);
  227. }
  228. int
  229. DIAMONDAPI
  230. SpdFdiClose(
  231. IN INT_PTR Handle
  232. )
  233. /*++
  234. Routine Description:
  235. Callback used by FDICopy to close files.
  236. Arguments:
  237. Handle - handle of file to close.
  238. Return Value:
  239. 0 (success).
  240. --*/
  241. {
  242. //
  243. // Don't close the target file because it screws up logic in FCopy().
  244. //
  245. if(Handle != CurrentTargetFileHandle) {
  246. _lclose((HFILE)Handle);
  247. }
  248. return(0);
  249. }
  250. LONG
  251. DIAMONDAPI
  252. SpdFdiSeek(
  253. IN INT_PTR Handle,
  254. IN long Distance,
  255. IN int SeekType
  256. )
  257. /*++
  258. Routine Description:
  259. Callback used by FDICopy to seek files.
  260. Arguments:
  261. Handle - handle of file to close.
  262. Distance - supplies distance to seek. Interpretation of this
  263. parameter depends on the value of SeekType.
  264. SeekType - supplies a value indicating how Distance is to be
  265. interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
  266. Return Value:
  267. New file offset or -1 if an error occurs.
  268. --*/
  269. {
  270. LONG rc;
  271. FYield();
  272. if(fUserQuit) {
  273. rc = -1L;
  274. } else {
  275. rc = _llseek((HFILE)Handle,Distance,SeekType);
  276. if(rc == HFILE_ERROR) {
  277. MyLastDiamondIoError = (Handle == CurrentTargetFileHandle)
  278. ? rcWriteSeekError
  279. : rcReadSeekError;
  280. rc = -1L;
  281. }
  282. }
  283. return(rc);
  284. }
  285. LONG
  286. DecompDiamondFile(
  287. PSTR SourceFileName,
  288. HANDLE TargetFileHandle,
  289. PFNWFROMW ProgressCallback,
  290. INT NumberOfTicks
  291. )
  292. {
  293. BOOL b;
  294. LONG rc;
  295. if(!FdiContext) {
  296. return(rcGenericDecompError);
  297. }
  298. MyLastDiamondWriteError = rcNoError;
  299. MyLastDiamondIoError = rcNoError;
  300. CurrentTargetFileHandle = (INT_PTR)TargetFileHandle;
  301. TicksForThisFile = NumberOfTicks;
  302. GaugeTicker = ProgressCallback;
  303. CurrentTargetFileSize = 0;
  304. fUserQuit = FALSE;
  305. //
  306. // The target file is opened exclusive by FCopy().
  307. // To avoid changing too much code this routine is passed the
  308. // open file handle instead of the target file name.
  309. // We can then return this file handle in the fdintCOPY_FILE
  310. // case in the fdi notification function (see above).
  311. //
  312. b = FDICopy(
  313. FdiContext,
  314. SourceFileName, // pass the whole path as the name
  315. "", // don't bother with the path part
  316. 0, // flags
  317. DiamondNotifyFunction,
  318. NULL, // no decryption
  319. (PVOID)TargetFileHandle // user data is target file handle
  320. );
  321. if(b) {
  322. rc = rcNoError;
  323. } else {
  324. if(fUserQuit) {
  325. rc = rcUserQuit;
  326. } else {
  327. switch(FdiError.erfOper) {
  328. case FDIERROR_CORRUPT_CABINET:
  329. rc = MyLastDiamondIoError;
  330. break;
  331. case FDIERROR_ALLOC_FAIL:
  332. rc = rcOutOfMemory;
  333. break;
  334. case FDIERROR_UNKNOWN_CABINET_VERSION:
  335. case FDIERROR_BAD_COMPR_TYPE:
  336. rc = rcUnknownAlgType;
  337. break;
  338. case FDIERROR_TARGET_FILE:
  339. rc = MyLastDiamondWriteError;
  340. break;
  341. case FDIERROR_USER_ABORT:
  342. rc = MyLastDiamondIoError;
  343. break;
  344. default:
  345. //
  346. // The rest of the errors are not handled specially.
  347. //
  348. rc = rcGenericDecompError;
  349. break;
  350. }
  351. }
  352. }
  353. return(rc);
  354. }
  355. BOOL
  356. IsDiamondFile(
  357. IN PSTR FileName
  358. )
  359. {
  360. FDICABINETINFO CabinetInfo;
  361. BOOL b;
  362. INT_PTR h;
  363. if(!FdiContext) {
  364. return(FALSE);
  365. }
  366. //
  367. // Open the file such that the handle is valid for use
  368. // in the diamond context (ie, seek, read routines above).
  369. //
  370. h = SpdFdiOpen(FileName,_O_RDONLY,0);
  371. if(h == -1) {
  372. return(FALSE);
  373. }
  374. b = FDIIsCabinet(FdiContext,h,&CabinetInfo);
  375. _lclose((HFILE)h);
  376. return(b);
  377. }
  378. BOOL
  379. InitDiamond(
  380. VOID
  381. )
  382. {
  383. if(FdiContext) {
  384. return(fTrue);
  385. }
  386. #ifdef MY_FDI_MEM_STATS
  387. DiAllocCount = DiFreeCount = 0;
  388. DiCurrentAllocation = DiPeakAllocation = 0;
  389. #endif
  390. //
  391. // Initialize a diamond context.
  392. //
  393. while((FdiContext = FDICreate(
  394. SpdFdiAlloc,
  395. SpdFdiFree,
  396. SpdFdiOpen,
  397. SpdFdiRead,
  398. SpdFdiWrite,
  399. SpdFdiClose,
  400. SpdFdiSeek,
  401. cpuUNKNOWN,
  402. &FdiError
  403. )) == NULL)
  404. {
  405. if (!FHandleOOM(hwndFrame)) {
  406. return(FALSE);
  407. }
  408. }
  409. return(TRUE);
  410. }
  411. VOID
  412. TermDiamond(
  413. VOID
  414. )
  415. {
  416. if(FdiContext) {
  417. FDIDestroy(FdiContext);
  418. FdiContext = NULL;
  419. }
  420. }