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.

1132 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. decomp.c
  5. Abstract:
  6. Routines to handle reading of files compressed into single-file
  7. cabinet format.
  8. Author:
  9. Ted Miller (tedm) 16 May 1997
  10. Revision History:
  11. --*/
  12. #include "..\lib\bootlib.h"
  13. #include "diamondd.h"
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <basetsd.h>
  17. #ifdef i386
  18. #include "bldrx86.h"
  19. #endif
  20. #if defined(_IA64_)
  21. #include "bldria64.h"
  22. #endif
  23. #if 0
  24. #define TmErrOut(x) DbgPrint x
  25. #define TmDbgOut(x) DbgPrint x
  26. #define TmDbgPause() DbgBreakPoint()
  27. #else
  28. #define TmErrOut(x)
  29. #define TmDbgOut(x)
  30. #define TmDbgPause()
  31. #endif
  32. BOOLEAN Decompress;
  33. //
  34. // Global variable that points to a buffer used for decompressing the file
  35. // being opened. After that, reads are satisfied from this buffer. The buffer
  36. // holds exactly one file at a time. We rely on the ordering of stuff in the loader
  37. // to ensure that only one file that needs to be decompressed is open at a time!
  38. //
  39. ULONG_PTR DecompressBufferBasePage;
  40. PVOID DecompressBuffer;
  41. ULONG DecompressBufferSize;
  42. BOOLEAN DecompressBufferInUse;
  43. ULONG SizeOfFileInDecompressBuffer;
  44. ULONG DecompExpectedSize;
  45. HFDI FdiContext;
  46. ERF DecompErf;
  47. //
  48. // The diamond stuff allocates and frees blocks of memory
  49. // for each file. There's no memory allocator in the boot loader that allows
  50. // for memory frees. So we have to fake it.
  51. //
  52. PVOID DecompressHeap;
  53. ULONG_PTR DecompressHeapPage;
  54. #define DECOMP_HEAP_SIZE ((128+2048)*1024) // 128K work + 2MB window
  55. typedef struct _DECOMP_HEAP_BLOCK {
  56. struct _DECOMP_HEAP_BLOCK *Next;
  57. ULONG BlockSize;
  58. BOOL Free;
  59. } DECOMP_HEAP_BLOCK, *PDECOMP_HEAP_BLOCK;
  60. VOID
  61. ReinitializeDiamondMiniHeap(
  62. VOID
  63. );
  64. //
  65. // Bogus global variable used to track the device id for the device that
  66. // the file we are currently decompressing lives on.
  67. //
  68. ULONG DecompDeviceId;
  69. ARC_STATUS DecompLastIoError;
  70. //
  71. // This is the value we return to diamond when it asks us to create
  72. // the target file.
  73. //
  74. #define DECOMP_MAGIC_HANDLE 0x87654
  75. //
  76. // Misc forward references.
  77. //
  78. ARC_STATUS
  79. DecompAllocateDecompressBuffer (
  80. IN ULONG BufferSize
  81. );
  82. VOID
  83. DecompFreeDecompressBuffer (
  84. VOID
  85. );
  86. ARC_STATUS
  87. DecompClose(
  88. IN ULONG FileId
  89. );
  90. ARC_STATUS
  91. DecompRead(
  92. IN ULONG FileId,
  93. OUT VOID * FIRMWARE_PTR Buffer,
  94. IN ULONG Length,
  95. OUT ULONG * FIRMWARE_PTR Transfer
  96. );
  97. ARC_STATUS
  98. DecompSeek(
  99. IN ULONG FileId,
  100. IN LARGE_INTEGER * FIRMWARE_PTR Offset,
  101. IN SEEK_MODE SeekMode
  102. );
  103. ARC_STATUS
  104. DecompGetFileInfo(
  105. IN ULONG FileId,
  106. OUT FILE_INFORMATION * FIRMWARE_PTR FileInfo
  107. );
  108. PVOID
  109. DIAMONDAPI
  110. DiamondAlloc(
  111. IN ULONG Size
  112. );
  113. VOID
  114. DIAMONDAPI
  115. DiamondFree(
  116. IN PVOID Block
  117. );
  118. INT_PTR
  119. DIAMONDAPI
  120. DiamondOpen(
  121. IN LPSTR FileName,
  122. IN int oflag,
  123. IN int pmode
  124. );
  125. UINT
  126. DIAMONDAPI
  127. DiamondRead(
  128. IN INT_PTR Handle,
  129. OUT PVOID pv,
  130. IN UINT ByteCount
  131. );
  132. UINT
  133. DIAMONDAPI
  134. DiamondWrite(
  135. IN INT_PTR Handle,
  136. IN PVOID pv,
  137. IN UINT ByteCount
  138. );
  139. int
  140. DIAMONDAPI
  141. DiamondClose(
  142. IN INT_PTR Handle
  143. );
  144. long
  145. DIAMONDAPI
  146. DiamondSeek(
  147. IN INT_PTR Handle,
  148. IN long Distance,
  149. IN int SeekType
  150. );
  151. INT_PTR
  152. DIAMONDAPI
  153. DiamondNotifyFunction(
  154. IN FDINOTIFICATIONTYPE Operation,
  155. IN PFDINOTIFICATION Parameters
  156. );
  157. //
  158. // Device dispatch table for our pseudo-filesystem.
  159. //
  160. BL_DEVICE_ENTRY_TABLE DecompDeviceEntryTable = { DecompClose, // close
  161. NULL, // mount
  162. NULL, // open
  163. DecompRead, // read
  164. NULL, // read status
  165. DecompSeek, // seek
  166. NULL, // write
  167. DecompGetFileInfo, // get file info
  168. NULL, // set file info
  169. NULL, // rename
  170. NULL, // get dirent
  171. NULL // PBOOTFS_INFO, unused
  172. };
  173. VOID
  174. DecompEnableDecompression(
  175. IN BOOLEAN Enable
  176. )
  177. {
  178. #if defined(_X86_) || defined(_IA64_)
  179. //
  180. // Disable on alpha, since it doesn't seem to work.
  181. //
  182. Decompress = Enable;
  183. #endif
  184. }
  185. BOOLEAN
  186. DecompGenerateCompressedName(
  187. IN LPCSTR Filename,
  188. OUT LPSTR CompressedName
  189. )
  190. /*++
  191. Routine Description:
  192. This routine generates the "compressed-form" name of a file.
  193. The compressed form substitutes the last character of the extension
  194. with a _. If there is no extension then ._ is appended to the name.
  195. Only the final component is relevent; others are preserved in the
  196. compressed form name.
  197. Arguments:
  198. Filename - supplies full pathname of file whose compressed form name
  199. is desired.
  200. CompressedName - receives compressed form of the full path. The caller must
  201. ensure that the buffer is large enough.
  202. Return Value:
  203. TRUE - the caller should try to locate the compressed filename first.
  204. FALSE - the caller should not attempt to locate the compressed filename
  205. at all.
  206. This value depends on the state of the Decompress global.
  207. --*/
  208. {
  209. PCHAR p,q;
  210. if(!Decompress) {
  211. return(FALSE);
  212. }
  213. strcpy(CompressedName,Filename);
  214. p = strrchr(CompressedName,'.');
  215. q = strrchr(CompressedName,'\\');
  216. if(q < p) {
  217. //
  218. // If there are 0, 1, or 2 characters after the dot, just append
  219. // the underscore. p points to the dot so include that in the length.
  220. //
  221. if(strlen(p) < 4) {
  222. strcat(CompressedName,"_");
  223. } else {
  224. //
  225. // Assume there are 3 characters in the extension and replace
  226. // the final one with an underscore.
  227. //
  228. p[3] = '_';
  229. }
  230. } else {
  231. //
  232. // No dot, just add ._.
  233. //
  234. strcat(CompressedName,"._");
  235. }
  236. return(TRUE);
  237. }
  238. DECOMP_STRUCTURE_CONTEXT DecompStructureContext = {0};
  239. ULONG
  240. DecompPrepareToReadCompressedFile(
  241. IN LPCSTR Filename,
  242. IN ULONG FileId
  243. )
  244. {
  245. ULONG Status;
  246. BOOL b;
  247. int err;
  248. ULONGLONG x;
  249. FDICABINETINFO CabinetInfo;
  250. ULONG OldUsableBase, OldUsableLimit;
  251. //
  252. // On both x86 and alpha the allocation of our large decompress buffer
  253. // has an unfortunate tendency to place the block right where the
  254. // (non-relocatable) kernel wants to go. By allocating from the top
  255. // of memory we make this problem go away.
  256. //
  257. if(!Decompress) {
  258. return((ULONG)(-1));
  259. }
  260. //
  261. // If we're in the middle of FDICopy or FDIIsCabinet then
  262. // we don't want to do our special processing. Special return code
  263. // of -1 tells the caller that we didn't process it.
  264. //
  265. if(FdiContext) {
  266. return((ULONG)(-1));
  267. }
  268. //
  269. // If there's no decompression heap yet, allocate one.
  270. //
  271. if(!DecompressHeap) {
  272. //
  273. // Set allocatable range to the decompression-specific range
  274. //
  275. OldUsableBase = BlUsableBase;
  276. OldUsableLimit = BlUsableLimit;
  277. BlUsableBase = BL_DECOMPRESS_RANGE_LOW;
  278. BlUsableLimit = BL_DECOMPRESS_RANGE_HIGH;
  279. Status = BlAllocateDescriptor(
  280. LoaderOsloaderHeap,
  281. 0,
  282. ROUND_TO_PAGES(DECOMP_HEAP_SIZE) >> PAGE_SHIFT,
  283. (PULONG)&DecompressHeapPage
  284. );
  285. //
  286. // Restore the previous alloc range.
  287. //
  288. BlUsableBase = OldUsableBase;
  289. BlUsableLimit = OldUsableLimit;
  290. if(Status != ESUCCESS) {
  291. TmErrOut(("Setup: couldn't allocate decompression heap (%u)\r\n",Status));
  292. DecompressHeap = NULL;
  293. return(Status);
  294. }
  295. DecompressHeap = (PVOID)(KSEG0_BASE | (DecompressHeapPage << PAGE_SHIFT));
  296. }
  297. //
  298. // We reinitialize diamond each time because of the way we deal with
  299. // the heap for alloc and free requests from diamond -- doing this
  300. // allows us to wipe our heap clean for each file.
  301. //
  302. ReinitializeDiamondMiniHeap();
  303. FdiContext = FDICreate(
  304. DiamondAlloc,
  305. DiamondFree,
  306. DiamondOpen,
  307. DiamondRead,
  308. DiamondWrite,
  309. DiamondClose,
  310. DiamondSeek,
  311. 0, // cpu type flag is ignored
  312. &DecompErf
  313. );
  314. if(!FdiContext) {
  315. TmErrOut(("Setup: FDICreate failed\r\n"));
  316. return(ENOMEM);
  317. }
  318. //
  319. // Check if file is a cabinet and reset file pointer.
  320. //
  321. b = FDIIsCabinet(FdiContext,FileId,&CabinetInfo);
  322. x = 0;
  323. BlSeek(FileId,(PLARGE_INTEGER)&x,SeekAbsolute);
  324. if(!b) {
  325. //
  326. // Not a cabinet, we're done. Bail with return code of -1
  327. // which tells the caller that everything's OK.
  328. //
  329. TmDbgOut(("Setup: file %s is not a cabinet\r\n",Filename));
  330. FDIDestroy(FdiContext);
  331. FdiContext = NULL;
  332. return((ULONG)(-1));
  333. }
  334. TmDbgOut(("Setup: file %s is compressed, prearing it for read\r\n",Filename));
  335. DecompDeviceId = BlFileTable[FileId].DeviceId;
  336. DecompLastIoError = ESUCCESS;
  337. b = FDICopy(
  338. FdiContext,
  339. "", // filename part only
  340. (LPSTR)Filename, // full path
  341. 0, // no flags relevent
  342. DiamondNotifyFunction, // routine to process control messages
  343. NULL, // no decryption
  344. NULL // no user-specified data
  345. );
  346. err = DecompErf.erfOper;
  347. FDIDestroy(FdiContext);
  348. FdiContext = NULL;
  349. if(b) {
  350. //
  351. // Everything worked.
  352. //
  353. // Get file information from the original file system so we can
  354. // return it later if someone wants it.
  355. //
  356. // Close the original file and switch context
  357. // structures so that read, seek, close, etc. requests come to us
  358. // instead of the original filesystem.
  359. //
  360. if(SizeOfFileInDecompressBuffer != DecompExpectedSize) {
  361. TmErrOut(("Setup: warning: expected size %lx, actual size = %lx\r\n",DecompExpectedSize,SizeOfFileInDecompressBuffer));
  362. }
  363. Status = BlGetFileInformation(FileId,&DecompStructureContext.FileInfo);
  364. if(Status != ESUCCESS) {
  365. TmErrOut(("DecompPrepareToReadCompressedFile: BlGetFileInfo returned %u\r\n",Status));
  366. DecompFreeDecompressBuffer();
  367. return(Status);
  368. }
  369. DecompStructureContext.FileInfo.EndingAddress.LowPart = SizeOfFileInDecompressBuffer;
  370. DecompStructureContext.FileInfo.EndingAddress.HighPart = 0;
  371. //
  372. // We don't handle files whose size doesn't fit in a DWORD.
  373. //
  374. if(DecompStructureContext.FileInfo.EndingAddress.HighPart) {
  375. TmErrOut(("DecompPrepareToReadCompressedFile: file too big\r\n"));
  376. DecompFreeDecompressBuffer();
  377. return(E2BIG);
  378. }
  379. BlClose(FileId);
  380. BlFileTable[FileId].Flags.Open = 1;
  381. BlFileTable[FileId].Position.QuadPart = 0;
  382. BlFileTable[FileId].DeviceEntryTable = &DecompDeviceEntryTable;
  383. #ifdef CACHE_DEVINFO
  384. BlFileTable[FileId].StructureContext = &DecompStructureContext;
  385. #else
  386. RtlCopyMemory(
  387. BlFileTable[FileId].StructureContext,
  388. &DecompStructureContext,
  389. sizeof(DECOMP_STRUCTURE_CONTEXT)
  390. );
  391. #endif
  392. return(ESUCCESS);
  393. } else {
  394. //
  395. // Failure.
  396. //
  397. TmErrOut(("Setupldr: FDICopy failed (FDIERROR = %u, last io err = %u)\r\n",err,DecompLastIoError));
  398. TmDbgPause();
  399. return(EINVAL);
  400. }
  401. }
  402. ARC_STATUS
  403. DecompAllocateDecompressBuffer (
  404. IN ULONG BufferSize
  405. )
  406. {
  407. ARC_STATUS Status;
  408. ULONG OldUsableBase, OldUsableLimit;
  409. //
  410. // On both x86 and alpha the allocation of our large decompress buffer
  411. // has an unfortunate tendency to place the block right where the
  412. // (non-relocatable) kernel wants to go. By allocating from the top
  413. // of memory we make this problem go away.
  414. //
  415. DecompressBufferSize = BufferSize;
  416. //
  417. // Set allocatable range to the decompression-specific range
  418. //
  419. OldUsableBase = BlUsableBase;
  420. OldUsableLimit = BlUsableLimit;
  421. BlUsableBase = BL_DECOMPRESS_RANGE_LOW;
  422. BlUsableLimit = BL_DECOMPRESS_RANGE_HIGH;
  423. Status = BlAllocateDescriptor(
  424. LoaderOsloaderHeap,
  425. 0,
  426. (ULONG)(ROUND_TO_PAGES(DecompressBufferSize) >> PAGE_SHIFT),
  427. (PULONG)&DecompressBufferBasePage
  428. );
  429. //
  430. // Restore the previous alloc range.
  431. //
  432. BlUsableBase = OldUsableBase;
  433. BlUsableLimit = OldUsableLimit;
  434. if ( Status != ESUCCESS ) {
  435. TmErrOut(("Setup: couldn't allocate decompression buffer (%u)\r\n",Status));
  436. DecompressBuffer = NULL;
  437. return(Status);
  438. }
  439. DecompressBuffer = (PVOID)(KSEG0_BASE | (DecompressBufferBasePage << PAGE_SHIFT));
  440. DecompressBufferInUse = TRUE;
  441. return ESUCCESS;
  442. }
  443. VOID
  444. DecompFreeDecompressBuffer (
  445. VOID
  446. )
  447. {
  448. if ( DecompressBufferInUse ) {
  449. DecompressBufferInUse = FALSE;
  450. BlFreeDescriptor( (ULONG)DecompressBufferBasePage );
  451. }
  452. if(DecompressHeap) {
  453. BlFreeDescriptor( (ULONG)DecompressHeapPage );
  454. DecompressHeap = NULL;
  455. }
  456. return;
  457. }
  458. ARC_STATUS
  459. DecompClose(
  460. IN ULONG FileId
  461. )
  462. /*++
  463. Routine Description:
  464. Close routine for decompression pseudo-filesystem.
  465. We mark the decompression buffer free and return success.
  466. Arguments:
  467. FileId - supplies open file id to be closed.
  468. Return Value:
  469. --*/
  470. {
  471. TmDbgOut(("DecompClose\r\n"));
  472. if(DecompressBufferInUse) {
  473. DecompFreeDecompressBuffer();
  474. } else {
  475. TmErrOut(("DecompClose: warning: no file buffered!\r\n"));
  476. TmDbgPause();
  477. }
  478. BlFileTable[FileId].Flags.Open = 0;
  479. return(ESUCCESS);
  480. }
  481. ARC_STATUS
  482. DecompRead(
  483. IN ULONG FileId,
  484. OUT VOID * FIRMWARE_PTR Buffer,
  485. IN ULONG Length,
  486. OUT ULONG * FIRMWARE_PTR Transfer
  487. )
  488. /*++
  489. Routine Description:
  490. Read routine for the decompression pseudo-filesystem.
  491. Reads are satisfied out of the decompression buffer.
  492. Arguments:
  493. FileId - supplies id for open file as returned by BlOpen().
  494. Buffer - receives data read from file.
  495. Length - supplies amount of data to be read, in bytes.
  496. Transfer - recieves number of bytes actually transferred
  497. into caller's buffer.
  498. Return Value:
  499. ARC status indicating outcome.
  500. --*/
  501. {
  502. ARC_STATUS Status;
  503. if(DecompressBufferInUse) {
  504. //
  505. // Make sure we don't try to read past EOF.
  506. //
  507. if((Length + BlFileTable[FileId].Position.LowPart) > SizeOfFileInDecompressBuffer) {
  508. TmErrOut(("DecompRead: warning: attempt to read past eof; read trucated\r\n"));
  509. TmDbgPause();
  510. Length = SizeOfFileInDecompressBuffer - BlFileTable[FileId].Position.LowPart;
  511. }
  512. //
  513. // Transfer data into caller's buffer.
  514. //
  515. TmDbgOut(("DecompRead: %lx bytes at filepos %lx\r\n",Length,BlFileTable[FileId].Position.LowPart));
  516. RtlCopyMemory(
  517. Buffer,
  518. (PCHAR)DecompressBuffer + BlFileTable[FileId].Position.LowPart,
  519. Length
  520. );
  521. *Transfer = Length;
  522. BlFileTable[FileId].Position.QuadPart += Length;
  523. Status = ESUCCESS;
  524. } else {
  525. //
  526. // Should never get here.
  527. //
  528. TmErrOut(("DecompRead: no file buffered!\r\n"));
  529. TmDbgPause();
  530. Status = EACCES;
  531. }
  532. return(Status);
  533. }
  534. ARC_STATUS
  535. DecompSeek(
  536. IN ULONG FileId,
  537. IN LARGE_INTEGER * FIRMWARE_PTR Offset,
  538. IN SEEK_MODE SeekMode
  539. )
  540. /*++
  541. Routine Description:
  542. Seek routine for the decompression pseudo-filesystem.
  543. Sets pseudo-file pointer to given offset.
  544. Arguments:
  545. FileId - supplies id for open file as returned by BlOpen().
  546. Offset - supplies new offset, whose interpretation depends on
  547. the SeekMode parameter.
  548. SeekMode - supplies type of seek. One of SeekAbsolute or SeekRelative.
  549. Return Value:
  550. ARC status indicating outcome.
  551. --*/
  552. {
  553. LONGLONG NewPosition;
  554. TmDbgOut(("DecompSeek: mode %u, pos = %lx\r\n",SeekMode,Offset->LowPart));
  555. if(DecompressBufferInUse) {
  556. switch(SeekMode) {
  557. case SeekAbsolute:
  558. NewPosition = Offset->QuadPart;
  559. break;
  560. case SeekRelative:
  561. NewPosition = BlFileTable[FileId].Position.QuadPart + Offset->QuadPart;
  562. break;
  563. default:
  564. TmErrOut(("DecompSeek: invalid seek mode\r\n"));
  565. TmDbgPause();
  566. return(EINVAL);
  567. }
  568. //
  569. // Make sure we don't try to seek to a negative offset or past EOF.
  570. //
  571. if(NewPosition < 0) {
  572. TmErrOut(("DecompSeek: warning: attempt to seek to negative offset\r\n"));
  573. TmDbgPause();
  574. NewPosition = 0;
  575. } else {
  576. if((ULONGLONG)NewPosition > (ULONGLONG)SizeOfFileInDecompressBuffer) {
  577. TmErrOut(("DecompSeek: attempt to seek past eof\r\n"));
  578. TmDbgPause();
  579. return(EINVAL);
  580. }
  581. }
  582. //
  583. // Remember new position.
  584. //
  585. TmDbgOut(("DecompSeek: new position is %lx\r\n",NewPosition));
  586. BlFileTable[FileId].Position.QuadPart = NewPosition;
  587. } else {
  588. //
  589. // Should never get here.
  590. //
  591. TmErrOut(("DecompSeek: no file buffered!\r\n"));
  592. TmDbgPause();
  593. return(EACCES);
  594. }
  595. return(ESUCCESS);
  596. }
  597. ARC_STATUS
  598. DecompGetFileInfo(
  599. IN ULONG FileId,
  600. OUT FILE_INFORMATION * FIRMWARE_PTR FileInfo
  601. )
  602. {
  603. RtlCopyMemory(
  604. FileInfo,
  605. &((PDECOMP_STRUCTURE_CONTEXT)BlFileTable[FileId].StructureContext)->FileInfo,
  606. sizeof(FILE_INFORMATION)
  607. );
  608. TmDbgOut(("DecompGetFileInfo: size = %lx\r\n",FileInfo->EndingAddress.LowPart));
  609. return(ESUCCESS);
  610. }
  611. VOID
  612. ReinitializeDiamondMiniHeap(
  613. VOID
  614. )
  615. {
  616. PDECOMP_HEAP_BLOCK p;
  617. p = DecompressHeap;
  618. p->BlockSize = DECOMP_HEAP_SIZE - sizeof(DECOMP_HEAP_BLOCK);
  619. p->Next = NULL;
  620. p->Free = TRUE;
  621. }
  622. PVOID
  623. DIAMONDAPI
  624. DiamondAlloc(
  625. IN ULONG Size
  626. )
  627. {
  628. PDECOMP_HEAP_BLOCK p,q;
  629. ULONG LeftOver;
  630. TmDbgOut(("DiamondAlloc: request %lx bytes\r\n",Size));
  631. //
  632. // Round size up to dword boundary.
  633. //
  634. if(Size % sizeof(ULONG_PTR)) {
  635. Size += sizeof(ULONG_PTR) - (Size % sizeof(ULONG_PTR));
  636. }
  637. //
  638. // Nothing fancy. First-fit algorithm, traversing all blocks
  639. // in the heap every time.
  640. //
  641. for(p=DecompressHeap; p; p=p->Next) {
  642. if(p->Free && (p->BlockSize >= Size)) {
  643. p->Free = FALSE;
  644. LeftOver = p->BlockSize - Size;
  645. if(LeftOver > sizeof(DECOMP_HEAP_BLOCK)) {
  646. //
  647. // Split the block.
  648. //
  649. p->BlockSize = Size;
  650. q = (PDECOMP_HEAP_BLOCK)((PUCHAR)(p+1) + Size);
  651. q->Next = p->Next;
  652. p->Next = q;
  653. q->Free = TRUE;
  654. q->BlockSize = LeftOver - sizeof(DECOMP_HEAP_BLOCK);
  655. }
  656. //
  657. // Return pointer to data area of the block.
  658. //
  659. TmDbgOut(("DiamondAlloc(%lx): %lx\r\n",Size,p+1));
  660. return(p+1);
  661. }
  662. }
  663. TmErrOut(("DiamondAlloc: out of heap space!\r\n"));
  664. TmDbgPause();
  665. return(NULL);
  666. }
  667. VOID
  668. DIAMONDAPI
  669. DiamondFree(
  670. IN PVOID Block
  671. )
  672. {
  673. PDECOMP_HEAP_BLOCK p;
  674. TmDbgOut(("DiamondFree(%lx)\r\n",Block));
  675. //
  676. // Get pointer to header for block.
  677. //
  678. Block = (PUCHAR)Block - sizeof(DECOMP_HEAP_BLOCK);
  679. //
  680. // Nothing fancy, no coalescing free blocks.
  681. //
  682. for(p=DecompressHeap; p; p=p->Next) {
  683. if(p == Block) {
  684. if(p->Free) {
  685. TmErrOut(("DiamondFree: warning: freeing free block\r\n"));
  686. TmDbgPause();
  687. return;
  688. }
  689. p->Free = TRUE;
  690. return;
  691. }
  692. }
  693. TmErrOut(("DiamondFree: warning: freeing invalid block\r\n"));
  694. TmDbgPause();
  695. }
  696. INT_PTR
  697. DIAMONDAPI
  698. DiamondOpen(
  699. IN LPSTR FileName,
  700. IN int oflag,
  701. IN int pmode
  702. )
  703. {
  704. ARC_STATUS Status;
  705. ULONG FileId;
  706. UNREFERENCED_PARAMETER(pmode);
  707. TmDbgOut(("DiamondOpen: %s\r\n",FileName));
  708. if(oflag & (_O_WRONLY | _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC | _O_EXCL)) {
  709. TmErrOut(("DiamondOpen: invalid oflag %lx for %s\r\n",oflag,FileName));
  710. TmDbgPause();
  711. DecompLastIoError = EINVAL;
  712. return(-1);
  713. }
  714. Status = BlOpen(DecompDeviceId,FileName,ArcOpenReadOnly,&FileId);
  715. if(Status != ESUCCESS) {
  716. TmErrOut(("DiamondOpen: BlOpen %s returned %u\r\n",FileName,Status));
  717. TmDbgPause();
  718. DecompLastIoError = Status;
  719. return(-1);
  720. } else {
  721. TmDbgOut(("DiamondOpen: handle to %s is %lx\r\n",FileName,FileId));
  722. }
  723. return((INT_PTR)FileId);
  724. }
  725. UINT
  726. DIAMONDAPI
  727. DiamondRead(
  728. IN INT_PTR Handle,
  729. OUT PVOID pv,
  730. IN UINT ByteCount
  731. )
  732. {
  733. ARC_STATUS Status;
  734. ULONG n;
  735. TmDbgOut(("DiamondRead: %lx bytes, handle %lx\r\n",ByteCount,Handle));
  736. //
  737. // We should never be asked to read from the target file.
  738. //
  739. if(Handle == DECOMP_MAGIC_HANDLE) {
  740. TmErrOut(("DiamondRead: called for unexpected file!\r\n"));
  741. TmDbgPause();
  742. DecompLastIoError = EACCES;
  743. return((UINT)(-1));
  744. }
  745. Status = BlRead((ULONG)Handle,pv,ByteCount,&n);
  746. if(Status != ESUCCESS) {
  747. TmErrOut(("DiamondRead: BlRead failed %u\r\n",Status));
  748. TmDbgPause();
  749. DecompLastIoError = Status;
  750. n = (UINT)(-1);
  751. }
  752. return(n);
  753. }
  754. UINT
  755. DIAMONDAPI
  756. DiamondWrite(
  757. IN INT_PTR Handle,
  758. IN PVOID pv,
  759. IN UINT ByteCount
  760. )
  761. {
  762. TmDbgOut(("DiamondWrite: %lx bytes\r\n",ByteCount));
  763. //
  764. // This guy should be called ONLY to write decompressed data
  765. // into the decompress buffer.
  766. //
  767. if(Handle != DECOMP_MAGIC_HANDLE) {
  768. TmErrOut(("DiamondWrite: called for unexpected file!\r\n"));
  769. TmDbgPause();
  770. DecompLastIoError = EACCES;
  771. return((UINT)(-1));
  772. }
  773. //
  774. // Check for overflow.
  775. //
  776. if(SizeOfFileInDecompressBuffer+ByteCount > DecompressBufferSize) {
  777. TmErrOut(("DiamondWrite: decompressed file too big!\r\n"));
  778. TmDbgPause();
  779. DecompLastIoError = E2BIG;
  780. return((UINT)(-1));
  781. }
  782. RtlCopyMemory(
  783. (PCHAR)DecompressBuffer + SizeOfFileInDecompressBuffer,
  784. pv,
  785. ByteCount
  786. );
  787. SizeOfFileInDecompressBuffer += ByteCount;
  788. return(ByteCount);
  789. }
  790. int
  791. DIAMONDAPI
  792. DiamondClose(
  793. IN INT_PTR Handle
  794. )
  795. {
  796. TmDbgOut(("DiamondClose, handle=%lx\r\n",Handle));
  797. if(Handle != DECOMP_MAGIC_HANDLE) {
  798. BlClose((ULONG)Handle);
  799. }
  800. return(0);
  801. }
  802. long
  803. DIAMONDAPI
  804. DiamondSeek(
  805. IN INT_PTR Handle,
  806. IN long Distance,
  807. IN int SeekType
  808. )
  809. {
  810. ARC_STATUS Status;
  811. LARGE_INTEGER Offset;
  812. TmDbgOut(("DiamondSeek: type=%u, dist=%lx, handle=%lx\r\n",SeekType,Distance,Handle));
  813. //
  814. // We should never be asked to seek in the output file.
  815. //
  816. if(Handle == DECOMP_MAGIC_HANDLE) {
  817. TmErrOut(("DiamondSeek: asked to seek target file!\r\n"));
  818. TmDbgPause();
  819. DecompLastIoError = EACCES;
  820. return(-1);
  821. }
  822. //
  823. // We can't handle seek from end of file.
  824. //
  825. if(SeekType == SEEK_END) {
  826. TmErrOut(("DiamondSeek: asked to seek relative to end of file!\r\n"));
  827. TmDbgPause();
  828. DecompLastIoError = EACCES;
  829. return(-1);
  830. }
  831. Offset.QuadPart = Distance;
  832. Status = BlSeek((ULONG)Handle,&Offset,SeekType);
  833. if(Status != ESUCCESS) {
  834. TmErrOut(("DiamondSeek: BlSeek(%lx,%x) returned %u\r\n",Distance,SeekType,Status));
  835. TmDbgPause();
  836. DecompLastIoError = Status;
  837. return(-1);
  838. }
  839. TmDbgOut(("DiamondSeek: BlSeek(%lx,%x) new file position is %lx\r\n",Distance,SeekType,BlFileTable[Handle].Position.LowPart));
  840. return((long)BlFileTable[Handle].Position.LowPart);
  841. }
  842. INT_PTR
  843. DIAMONDAPI
  844. DiamondNotifyFunction(
  845. IN FDINOTIFICATIONTYPE Operation,
  846. IN PFDINOTIFICATION Parameters
  847. )
  848. {
  849. ARC_STATUS Status;
  850. switch(Operation) {
  851. case fdintCABINET_INFO:
  852. //
  853. // Nothing interesting here. Return 0 to continue.
  854. //
  855. return(0);
  856. case fdintCOPY_FILE:
  857. //
  858. // The file was obviously a cabinet so we're going to extract
  859. // the file out of it. Rememember that the decompression buffer
  860. // is in use. If it's already in use, then a fundamental
  861. // principle of our implementation has been violated and we
  862. // must bail now.
  863. //
  864. if(DecompressBufferInUse) {
  865. TmErrOut(("DiamondNotifyFunction: opens overlap (%s)!\r\n",Parameters->psz1));
  866. DecompLastIoError = EACCES;
  867. return(-1);
  868. }
  869. DecompExpectedSize = Parameters->cb;
  870. Status = DecompAllocateDecompressBuffer( DecompExpectedSize );
  871. if (Status != ESUCCESS) {
  872. TmErrOut(("DiamondNotifyFunction: unable to allocate decompress buffer!\r\n"));
  873. return(-1);
  874. }
  875. SizeOfFileInDecompressBuffer = 0;
  876. return(DECOMP_MAGIC_HANDLE);
  877. case fdintCLOSE_FILE_INFO:
  878. //
  879. // Diamond is asking to close the target handle. There's nothing we really
  880. // care about here, just return success as long as we recognize the handle.
  881. //
  882. if(Parameters->hf == DECOMP_MAGIC_HANDLE) {
  883. return(TRUE);
  884. } else {
  885. TmErrOut(("DiamondNotifyFunction: asked to close unexpected file!\r\n"));
  886. TmDbgPause();
  887. DecompLastIoError = EINVAL;
  888. return(FALSE);
  889. }
  890. default:
  891. //
  892. // Disregard any other messages
  893. //
  894. return(0);
  895. }
  896. }