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.

1710 lines
60 KiB

  1. #include "pch.h"
  2. #include "compress.h"
  3. #include "mrcicode.h"
  4. #define COMPRESS_SIG 0x434F4D50 //COMP
  5. #define COMPRESS_CONT_SIG 0x434F4D43 //COMC
  6. #define COMPRESS_NEWFILE 0x434F4D46 //COMF
  7. #define COMPRESS_BUFFER_SIZE 0x8000 //32K
  8. #define COMPRESS_DEFAULT_SIZE 0x7FFFFFFF //2GB
  9. BOOL g_ErrorMode = FALSE;
  10. unsigned
  11. CompressData(
  12. IN CompressionType Type,
  13. IN PBYTE Data,
  14. IN unsigned DataSize,
  15. OUT PBYTE CompressedData,
  16. IN unsigned BufferSize
  17. )
  18. {
  19. unsigned u;
  20. switch(Type) {
  21. case CompressNone:
  22. default:
  23. //
  24. // Force caller to do something intelligent, such as
  25. // writing directly out of the uncompressed buffer.
  26. // This avoids an extra memory move.
  27. //
  28. u = (unsigned)(-1);
  29. break;
  30. case CompressMrci1:
  31. u = Mrci1MaxCompress(Data,DataSize,CompressedData,BufferSize);
  32. break;
  33. case CompressMrci2:
  34. u = Mrci2MaxCompress(Data,DataSize,CompressedData,BufferSize);
  35. break;
  36. }
  37. return(u);
  38. }
  39. unsigned
  40. DecompressData(
  41. IN CompressionType Type,
  42. IN PBYTE CompressedData,
  43. IN unsigned CompressedDataSize,
  44. OUT PBYTE DecompressedData,
  45. IN unsigned BufferSize
  46. )
  47. {
  48. unsigned u;
  49. switch(Type) {
  50. case CompressNone:
  51. if(BufferSize >= CompressedDataSize) {
  52. memmove(DecompressedData,CompressedData,CompressedDataSize);
  53. u = CompressedDataSize;
  54. } else {
  55. u = (unsigned)(-1);
  56. }
  57. break;
  58. case CompressMrci1:
  59. u = Mrci1Decompress(CompressedData,CompressedDataSize,DecompressedData,BufferSize);
  60. break;
  61. case CompressMrci2:
  62. u = Mrci2Decompress(CompressedData,CompressedDataSize,DecompressedData,BufferSize);
  63. break;
  64. default:
  65. u = (unsigned)(-1);
  66. break;
  67. }
  68. return(u);
  69. }
  70. VOID
  71. CompressCleanupHandleA (
  72. IN OUT PCOMPRESS_HANDLEA CompressedHandle
  73. )
  74. {
  75. if (CompressedHandle) {
  76. if (CompressedHandle->ReadBuffer) {
  77. MemFree (g_hHeap, 0, CompressedHandle->ReadBuffer);
  78. }
  79. if (CompressedHandle->ExtraBuffer) {
  80. MemFree (g_hHeap, 0, CompressedHandle->ExtraBuffer);
  81. }
  82. if (CompressedHandle->CompBuffer) {
  83. MemFree (g_hHeap, 0, CompressedHandle->CompBuffer);
  84. }
  85. if (CompressedHandle->StorePath) {
  86. FreePathStringA (CompressedHandle->StorePath);
  87. }
  88. if (CompressedHandle->MainFilePattern) {
  89. FreePathStringA (CompressedHandle->MainFilePattern);
  90. }
  91. if ((CompressedHandle->CurrFileHandle) &&
  92. (CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
  93. ) {
  94. CloseHandle (CompressedHandle->CurrFileHandle);
  95. }
  96. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
  97. }
  98. }
  99. VOID
  100. CompressCleanupHandleW (
  101. IN OUT PCOMPRESS_HANDLEW CompressedHandle
  102. )
  103. {
  104. if (CompressedHandle) {
  105. if (CompressedHandle->ReadBuffer) {
  106. MemFree (g_hHeap, 0, CompressedHandle->ReadBuffer);
  107. }
  108. if (CompressedHandle->ExtraBuffer) {
  109. MemFree (g_hHeap, 0, CompressedHandle->ExtraBuffer);
  110. }
  111. if (CompressedHandle->CompBuffer) {
  112. MemFree (g_hHeap, 0, CompressedHandle->CompBuffer);
  113. }
  114. if (CompressedHandle->StorePath) {
  115. FreePathStringW (CompressedHandle->StorePath);
  116. }
  117. if (CompressedHandle->MainFilePattern) {
  118. FreePathStringW (CompressedHandle->MainFilePattern);
  119. }
  120. if ((CompressedHandle->CurrFileHandle) &&
  121. (CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
  122. ) {
  123. CloseHandle (CompressedHandle->CurrFileHandle);
  124. }
  125. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
  126. }
  127. }
  128. BOOL
  129. CompressCreateHandleA (
  130. IN PCSTR StorePath,
  131. IN PCSTR MainFilePattern,
  132. IN UINT StartIndex,
  133. IN LONGLONG MaxFileSize,
  134. OUT PCOMPRESS_HANDLEA CompressedHandle
  135. )
  136. {
  137. CHAR currFile [1024];
  138. PCSTR currFullPath = NULL;
  139. DWORD signature = COMPRESS_SIG;
  140. BOOL result = FALSE;
  141. __try {
  142. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
  143. if (StartIndex == 0) {
  144. CompressedHandle->CurrFileIndex = 1;
  145. } else {
  146. CompressedHandle->CurrFileIndex = StartIndex;
  147. }
  148. CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
  149. if (MaxFileSize == 0) {
  150. CompressedHandle->MaxFileSize = COMPRESS_DEFAULT_SIZE;
  151. } else {
  152. CompressedHandle->MaxFileSize = MaxFileSize;
  153. }
  154. CompressedHandle->StorePath = DuplicatePathStringA (StorePath, 0);
  155. if (!CompressedHandle->StorePath) {
  156. __leave;
  157. }
  158. CompressedHandle->MainFilePattern = DuplicatePathStringA (MainFilePattern, 0);
  159. if (!CompressedHandle->MainFilePattern) {
  160. __leave;
  161. }
  162. wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  163. currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
  164. CompressedHandle->CurrFileHandle = BfCreateFileA (currFullPath);
  165. if ((CompressedHandle->CurrFileHandle == NULL) ||
  166. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  167. ) {
  168. __leave;
  169. }
  170. FreePathStringA (currFullPath);
  171. currFullPath = NULL;
  172. // write the signature
  173. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  174. __leave;
  175. }
  176. CompressedHandle->CurrFileSize += sizeof (DWORD);
  177. // reserve room for writing how many files we stored
  178. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  179. __leave;
  180. }
  181. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  182. CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  183. if (!CompressedHandle->ReadBuffer) {
  184. __leave;
  185. }
  186. CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  187. if (!CompressedHandle->CompBuffer) {
  188. __leave;
  189. }
  190. CompressedHandle->ExtraBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  191. if (!CompressedHandle->ExtraBuffer) {
  192. __leave;
  193. }
  194. result = TRUE;
  195. }
  196. __finally {
  197. PushError ();
  198. if (currFullPath) {
  199. FreePathStringA (currFullPath);
  200. currFullPath = NULL;
  201. }
  202. if (!result) {
  203. CompressCleanupHandleA (CompressedHandle);
  204. }
  205. PopError ();
  206. }
  207. return result;
  208. }
  209. BOOL
  210. CompressCreateHandleW (
  211. IN PCWSTR StorePath,
  212. IN PCWSTR MainFilePattern,
  213. IN UINT StartIndex,
  214. IN LONGLONG MaxFileSize,
  215. OUT PCOMPRESS_HANDLEW CompressedHandle
  216. )
  217. {
  218. WCHAR currFile [1024];
  219. PCWSTR currFullPath = NULL;
  220. DWORD signature = COMPRESS_SIG;
  221. BOOL result = FALSE;
  222. __try {
  223. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
  224. if (StartIndex == 0) {
  225. CompressedHandle->CurrFileIndex = 1;
  226. } else {
  227. CompressedHandle->CurrFileIndex = StartIndex;
  228. }
  229. CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
  230. if (MaxFileSize == 0) {
  231. CompressedHandle->MaxFileSize = COMPRESS_DEFAULT_SIZE;
  232. } else {
  233. CompressedHandle->MaxFileSize = MaxFileSize;
  234. }
  235. CompressedHandle->StorePath = DuplicatePathStringW (StorePath, 0);
  236. if (!CompressedHandle->StorePath) {
  237. __leave;
  238. }
  239. CompressedHandle->MainFilePattern = DuplicatePathStringW (MainFilePattern, 0);
  240. if (!CompressedHandle->MainFilePattern) {
  241. __leave;
  242. }
  243. wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  244. currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
  245. CompressedHandle->CurrFileHandle = BfCreateFileW (currFullPath);
  246. if ((CompressedHandle->CurrFileHandle == NULL) ||
  247. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  248. ) {
  249. __leave;
  250. }
  251. FreePathStringW (currFullPath);
  252. currFullPath = NULL;
  253. // write the signature
  254. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  255. __leave;
  256. }
  257. CompressedHandle->CurrFileSize += sizeof (DWORD);
  258. // reserve room for writing how many files we stored
  259. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  260. __leave;
  261. }
  262. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  263. CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  264. if (!CompressedHandle->ReadBuffer) {
  265. __leave;
  266. }
  267. CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  268. if (!CompressedHandle->CompBuffer) {
  269. __leave;
  270. }
  271. CompressedHandle->ExtraBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  272. if (!CompressedHandle->ExtraBuffer) {
  273. __leave;
  274. }
  275. result = TRUE;
  276. }
  277. __finally {
  278. PushError ();
  279. if (currFullPath) {
  280. FreePathStringW (currFullPath);
  281. currFullPath = NULL;
  282. }
  283. if (!result) {
  284. CompressCleanupHandleW (CompressedHandle);
  285. }
  286. PopError ();
  287. }
  288. return result;
  289. }
  290. BOOL
  291. pPrepareNextFileA (
  292. IN OUT PCOMPRESS_HANDLEA CompressedHandle,
  293. IN BOOL ReadOnly
  294. )
  295. {
  296. CHAR currFile [1024];
  297. PCSTR currFullPath = NULL;
  298. DWORD signature = COMPRESS_SIG;
  299. LONGLONG contSig = COMPRESS_CONT_SIG;
  300. BOOL result = FALSE;
  301. __try {
  302. if ((CompressedHandle->CurrFileHandle == NULL) ||
  303. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  304. ) {
  305. __leave;
  306. }
  307. if (!CloseHandle (CompressedHandle->CurrFileHandle)) {
  308. __leave;
  309. }
  310. CompressedHandle->CurrFileSize = 0;
  311. CompressedHandle->CurrFileIndex ++;
  312. wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  313. currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
  314. if (ReadOnly) {
  315. CompressedHandle->CurrFileHandle = BfOpenReadFileA (currFullPath);
  316. } else {
  317. CompressedHandle->CurrFileHandle = BfCreateFileA (currFullPath);
  318. }
  319. if ((CompressedHandle->CurrFileHandle == NULL) ||
  320. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  321. ) {
  322. __leave;
  323. }
  324. FreePathStringA (currFullPath);
  325. currFullPath = NULL;
  326. if (ReadOnly) {
  327. // read the signature
  328. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  329. __leave;
  330. }
  331. CompressedHandle->CurrFileSize += sizeof (DWORD);
  332. if (signature != COMPRESS_SIG) {
  333. SetLastError (ERROR_INVALID_DATA);
  334. __leave;
  335. }
  336. // read special continuation signature
  337. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
  338. __leave;
  339. }
  340. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  341. if (CompressedHandle->CurrFileIndex > 1) {
  342. if (contSig != COMPRESS_CONT_SIG) {
  343. SetLastError (ERROR_INVALID_DATA);
  344. __leave;
  345. }
  346. }
  347. } else {
  348. // write the signature
  349. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  350. __leave;
  351. }
  352. CompressedHandle->CurrFileSize += sizeof (DWORD);
  353. // write special continuation signature
  354. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
  355. __leave;
  356. }
  357. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  358. }
  359. result = TRUE;
  360. }
  361. __finally {
  362. PushError ();
  363. if (currFullPath) {
  364. FreePathStringA (currFullPath);
  365. currFullPath = NULL;
  366. }
  367. PopError ();
  368. }
  369. return result;
  370. }
  371. BOOL
  372. pPrepareNextFileW (
  373. IN OUT PCOMPRESS_HANDLEW CompressedHandle,
  374. IN BOOL ReadOnly
  375. )
  376. {
  377. WCHAR currFile [1024];
  378. PCWSTR currFullPath = NULL;
  379. DWORD signature = COMPRESS_SIG;
  380. LONGLONG contSig = COMPRESS_CONT_SIG;
  381. BOOL result = FALSE;
  382. __try {
  383. if ((CompressedHandle->CurrFileHandle == NULL) ||
  384. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  385. ) {
  386. __leave;
  387. }
  388. if (!CloseHandle (CompressedHandle->CurrFileHandle)) {
  389. __leave;
  390. }
  391. CompressedHandle->CurrFileSize = 0;
  392. CompressedHandle->CurrFileIndex ++;
  393. wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  394. currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
  395. if (ReadOnly) {
  396. CompressedHandle->CurrFileHandle = BfOpenReadFileW (currFullPath);
  397. } else {
  398. CompressedHandle->CurrFileHandle = BfCreateFileW (currFullPath);
  399. }
  400. if ((CompressedHandle->CurrFileHandle == NULL) ||
  401. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  402. ) {
  403. __leave;
  404. }
  405. FreePathStringW (currFullPath);
  406. currFullPath = NULL;
  407. if (ReadOnly) {
  408. // read the signature
  409. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  410. __leave;
  411. }
  412. CompressedHandle->CurrFileSize += sizeof (DWORD);
  413. if (signature != COMPRESS_SIG) {
  414. SetLastError (ERROR_INVALID_DATA);
  415. __leave;
  416. }
  417. // read special continuation signature
  418. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
  419. __leave;
  420. }
  421. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  422. if (CompressedHandle->CurrFileIndex > 1) {
  423. if (contSig != COMPRESS_CONT_SIG) {
  424. SetLastError (ERROR_INVALID_DATA);
  425. __leave;
  426. }
  427. }
  428. } else {
  429. // write the signature
  430. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  431. __leave;
  432. }
  433. CompressedHandle->CurrFileSize += sizeof (DWORD);
  434. // write special continuation signature
  435. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&contSig), sizeof (LONGLONG))) {
  436. __leave;
  437. }
  438. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  439. }
  440. result = TRUE;
  441. }
  442. __finally {
  443. PushError ();
  444. if (currFullPath) {
  445. FreePathStringW (currFullPath);
  446. currFullPath = NULL;
  447. }
  448. PopError ();
  449. }
  450. return result;
  451. }
  452. BOOL
  453. pDeleteNextFilesA (
  454. IN PCOMPRESS_HANDLEA CompressedHandle,
  455. IN UINT SavedIndex
  456. )
  457. {
  458. CHAR currFile [1024];
  459. PCSTR currFullPath = NULL;
  460. while (TRUE) {
  461. wsprintfA (currFile, CompressedHandle->MainFilePattern, SavedIndex);
  462. currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
  463. if (currFullPath) {
  464. if (DoesFileExistA (currFullPath)) {
  465. DeleteFileA (currFullPath);
  466. } else {
  467. break;
  468. }
  469. FreePathStringA (currFullPath);
  470. currFullPath = NULL;
  471. }
  472. SavedIndex ++;
  473. }
  474. if (currFullPath) {
  475. FreePathStringA (currFullPath);
  476. currFullPath = NULL;
  477. }
  478. return TRUE;
  479. }
  480. BOOL
  481. pDeleteNextFilesW (
  482. IN PCOMPRESS_HANDLEW CompressedHandle,
  483. IN UINT SavedIndex
  484. )
  485. {
  486. WCHAR currFile [1024];
  487. PCWSTR currFullPath = NULL;
  488. while (TRUE) {
  489. wsprintfW (currFile, CompressedHandle->MainFilePattern, SavedIndex);
  490. currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
  491. if (currFullPath) {
  492. if (DoesFileExistW (currFullPath)) {
  493. DeleteFileW (currFullPath);
  494. } else {
  495. break;
  496. }
  497. FreePathStringW (currFullPath);
  498. currFullPath = NULL;
  499. }
  500. SavedIndex ++;
  501. }
  502. if (currFullPath) {
  503. FreePathStringW (currFullPath);
  504. currFullPath = NULL;
  505. }
  506. return TRUE;
  507. }
  508. BOOL
  509. CompressAddFileToHandleA (
  510. IN PCSTR FileName,
  511. IN PCSTR StoredName,
  512. IN OUT PCOMPRESS_HANDLEA CompressedHandle
  513. )
  514. {
  515. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  516. LONGLONG fileSize;
  517. DWORD bytesRead;
  518. DWORD bytesWritten;
  519. DWORD bytesComp;
  520. DWORD bytesUncomp;
  521. DWORD signature = COMPRESS_NEWFILE;
  522. DWORD fileNameSize;
  523. DWORD headerSize;
  524. USHORT compType = 0;
  525. USHORT compSize = 0;
  526. PCWSTR unicodeName = NULL;
  527. UINT savedIndex = 0;
  528. LARGE_INTEGER savedSize;
  529. BOOL result = FALSE;
  530. __try {
  531. // save the state of the compress handle
  532. savedIndex = CompressedHandle->CurrFileIndex;
  533. savedSize.QuadPart = CompressedHandle->CurrFileSize;
  534. fileSize = BfGetFileSizeA (FileName);
  535. fileHandle = BfOpenReadFileA (FileName);
  536. if ((fileHandle == NULL) ||
  537. (fileHandle == INVALID_HANDLE_VALUE)
  538. ) {
  539. __leave;
  540. }
  541. // handle UNICODE files
  542. unicodeName = ConvertAtoW (StoredName);
  543. if (!unicodeName) {
  544. __leave;
  545. }
  546. fileNameSize = SizeOfStringW (unicodeName);
  547. headerSize = sizeof (DWORD) + sizeof (LONGLONG) + sizeof (DWORD) + fileNameSize;
  548. if (CompressedHandle->CurrFileSize + headerSize > CompressedHandle->MaxFileSize) {
  549. if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
  550. __leave;
  551. }
  552. }
  553. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  554. __leave;
  555. }
  556. CompressedHandle->CurrFileSize += sizeof (DWORD);
  557. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
  558. __leave;
  559. }
  560. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  561. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
  562. __leave;
  563. }
  564. CompressedHandle->CurrFileSize += sizeof (DWORD);
  565. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(unicodeName), fileNameSize)) {
  566. __leave;
  567. }
  568. CompressedHandle->CurrFileSize += fileNameSize;
  569. FreeConvertedStr (unicodeName);
  570. unicodeName = NULL;
  571. while (fileSize) {
  572. ZeroMemory (CompressedHandle->ReadBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  573. ZeroMemory (CompressedHandle->CompBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  574. if (!ReadFile (fileHandle, CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), COMPRESS_BUFFER_SIZE, &bytesRead, NULL)) {
  575. __leave;
  576. }
  577. if (bytesRead == 0)
  578. {
  579. // Somehow the file points is beyond the end of the file. Probably file in use.
  580. SetLastError(ERROR_SHARING_VIOLATION);
  581. __leave;
  582. }
  583. bytesComp = CompressData (
  584. CompressMrci1,
  585. CompressedHandle->ReadBuffer + 2 * sizeof (USHORT),
  586. bytesRead,
  587. CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
  588. COMPRESS_BUFFER_SIZE
  589. );
  590. if (bytesComp < bytesRead) {
  591. bytesUncomp = DecompressData (
  592. CompressMrci1,
  593. CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
  594. bytesComp,
  595. CompressedHandle->ExtraBuffer,
  596. COMPRESS_BUFFER_SIZE
  597. );
  598. if (bytesUncomp != bytesRead) {
  599. bytesComp = COMPRESS_BUFFER_SIZE;
  600. } else {
  601. if (!TestBuffer (CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), CompressedHandle->ExtraBuffer, bytesRead)) {
  602. bytesComp = COMPRESS_BUFFER_SIZE;
  603. }
  604. }
  605. }
  606. if (bytesComp >= bytesRead) {
  607. compType = CompressNone;
  608. compSize = (USHORT)bytesRead;
  609. CopyMemory (CompressedHandle->ReadBuffer, &compType, sizeof (USHORT));
  610. CopyMemory (CompressedHandle->ReadBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
  611. compSize += (2 * sizeof (USHORT));
  612. if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
  613. if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
  614. __leave;
  615. }
  616. }
  617. if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->ReadBuffer, compSize)) {
  618. __leave;
  619. }
  620. CompressedHandle->CurrFileSize += compSize;
  621. } else {
  622. compType = CompressMrci1;
  623. compSize = (USHORT)bytesComp;
  624. CopyMemory (CompressedHandle->CompBuffer, &compType, sizeof (USHORT));
  625. CopyMemory (CompressedHandle->CompBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
  626. compSize += (2 * sizeof (USHORT));
  627. if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
  628. if (!pPrepareNextFileA (CompressedHandle, FALSE)) {
  629. __leave;
  630. }
  631. }
  632. if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
  633. __leave;
  634. }
  635. CompressedHandle->CurrFileSize += compSize;
  636. }
  637. fileSize -= bytesRead;
  638. }
  639. CompressedHandle->FilesStored ++;
  640. result = TRUE;
  641. }
  642. __finally {
  643. PushError ();
  644. if (unicodeName) {
  645. FreeConvertedStr (unicodeName);
  646. unicodeName = NULL;
  647. }
  648. if (fileHandle != INVALID_HANDLE_VALUE) {
  649. CloseHandle (fileHandle);
  650. }
  651. if (!result) {
  652. // let's restore the state of the compress handle
  653. if (savedIndex == CompressedHandle->CurrFileIndex) {
  654. if (savedSize.QuadPart != CompressedHandle->CurrFileSize) {
  655. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  656. SetEndOfFile (CompressedHandle->CurrFileHandle);
  657. CompressedHandle->CurrFileSize = savedSize.QuadPart;
  658. }
  659. } else {
  660. CompressedHandle->CurrFileIndex = savedIndex - 1;
  661. pPrepareNextFileA (CompressedHandle, TRUE);
  662. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  663. SetEndOfFile (CompressedHandle->CurrFileHandle);
  664. CompressedHandle->CurrFileSize = savedSize.QuadPart;
  665. pDeleteNextFilesA (CompressedHandle, savedIndex);
  666. }
  667. }
  668. PopError ();
  669. }
  670. return result;
  671. }
  672. BOOL
  673. CompressAddFileToHandleW (
  674. IN PCWSTR FileName,
  675. IN PCWSTR StoredName,
  676. IN OUT PCOMPRESS_HANDLEW CompressedHandle
  677. )
  678. {
  679. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  680. LONGLONG fileSize;
  681. DWORD bytesRead;
  682. DWORD bytesWritten;
  683. DWORD bytesComp;
  684. DWORD bytesUncomp;
  685. DWORD signature = COMPRESS_NEWFILE;
  686. DWORD fileNameSize;
  687. DWORD headerSize;
  688. USHORT compType = 0;
  689. USHORT compSize = 0;
  690. UINT savedIndex = 0;
  691. LARGE_INTEGER savedSize;
  692. BOOL result = FALSE;
  693. __try {
  694. // save the state of the compress handle
  695. savedIndex = CompressedHandle->CurrFileIndex;
  696. savedSize.QuadPart = CompressedHandle->CurrFileSize;
  697. fileSize = BfGetFileSizeW (FileName);
  698. fileHandle = BfOpenReadFileW (FileName);
  699. if ((fileHandle == NULL) ||
  700. (fileHandle == INVALID_HANDLE_VALUE)
  701. ) {
  702. __leave;
  703. }
  704. fileNameSize = SizeOfStringW (StoredName);
  705. headerSize = sizeof (DWORD) + sizeof (LONGLONG) + sizeof (DWORD) + fileNameSize;
  706. if (CompressedHandle->CurrFileSize + headerSize > CompressedHandle->MaxFileSize) {
  707. if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
  708. __leave;
  709. }
  710. }
  711. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  712. __leave;
  713. }
  714. CompressedHandle->CurrFileSize += sizeof (DWORD);
  715. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
  716. __leave;
  717. }
  718. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  719. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
  720. __leave;
  721. }
  722. CompressedHandle->CurrFileSize += sizeof (DWORD);
  723. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(StoredName), fileNameSize)) {
  724. __leave;
  725. }
  726. CompressedHandle->CurrFileSize += fileNameSize;
  727. while (fileSize) {
  728. ZeroMemory (CompressedHandle->ReadBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  729. ZeroMemory (CompressedHandle->CompBuffer, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  730. if (!ReadFile (fileHandle, CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), COMPRESS_BUFFER_SIZE, &bytesRead, NULL)) {
  731. __leave;
  732. }
  733. if (bytesRead == 0)
  734. {
  735. // Somehow the file points is beyond the end of the file. Probably file in use.
  736. SetLastError(ERROR_SHARING_VIOLATION);
  737. __leave;
  738. }
  739. bytesComp = CompressData (
  740. CompressMrci1,
  741. CompressedHandle->ReadBuffer + 2 * sizeof (USHORT),
  742. bytesRead,
  743. CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
  744. COMPRESS_BUFFER_SIZE
  745. );
  746. if (bytesComp < bytesRead) {
  747. bytesUncomp = DecompressData (
  748. CompressMrci1,
  749. CompressedHandle->CompBuffer + 2 * sizeof (USHORT),
  750. bytesComp,
  751. CompressedHandle->ExtraBuffer,
  752. COMPRESS_BUFFER_SIZE
  753. );
  754. if (bytesUncomp != bytesRead) {
  755. bytesComp = COMPRESS_BUFFER_SIZE;
  756. } else {
  757. if (!TestBuffer (CompressedHandle->ReadBuffer + 2 * sizeof (USHORT), CompressedHandle->ExtraBuffer, bytesRead)) {
  758. bytesComp = COMPRESS_BUFFER_SIZE;
  759. }
  760. }
  761. }
  762. if (bytesComp >= bytesRead) {
  763. compType = CompressNone;
  764. compSize = (USHORT)bytesRead;
  765. CopyMemory (CompressedHandle->ReadBuffer, &compType, sizeof (USHORT));
  766. CopyMemory (CompressedHandle->ReadBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
  767. compSize += (2 * sizeof (USHORT));
  768. if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
  769. if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
  770. __leave;
  771. }
  772. }
  773. if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->ReadBuffer, compSize)) {
  774. __leave;
  775. }
  776. CompressedHandle->CurrFileSize += compSize;
  777. } else {
  778. compType = CompressMrci1;
  779. compSize = (USHORT)bytesComp;
  780. CopyMemory (CompressedHandle->CompBuffer, &compType, sizeof (USHORT));
  781. CopyMemory (CompressedHandle->CompBuffer + sizeof (USHORT), &compSize, sizeof (USHORT));
  782. compSize += (2 * sizeof (USHORT));
  783. if (CompressedHandle->CurrFileSize + compSize > CompressedHandle->MaxFileSize) {
  784. if (!pPrepareNextFileW (CompressedHandle, FALSE)) {
  785. __leave;
  786. }
  787. }
  788. if (!BfWriteFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
  789. __leave;
  790. }
  791. CompressedHandle->CurrFileSize += compSize;
  792. }
  793. fileSize -= bytesRead;
  794. }
  795. CompressedHandle->FilesStored ++;
  796. result = TRUE;
  797. }
  798. __finally {
  799. PushError ();
  800. if (fileHandle != INVALID_HANDLE_VALUE) {
  801. CloseHandle (fileHandle);
  802. }
  803. if (!result) {
  804. // let's restore the state of the compress handle
  805. if (savedIndex == CompressedHandle->CurrFileIndex) {
  806. if (savedSize.QuadPart != CompressedHandle->CurrFileSize) {
  807. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  808. SetEndOfFile (CompressedHandle->CurrFileHandle);
  809. CompressedHandle->CurrFileSize = savedSize.QuadPart;
  810. }
  811. } else {
  812. CompressedHandle->CurrFileIndex = savedIndex - 1;
  813. pPrepareNextFileW (CompressedHandle, TRUE);
  814. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  815. SetEndOfFile (CompressedHandle->CurrFileHandle);
  816. CompressedHandle->CurrFileSize = savedSize.QuadPart;
  817. pDeleteNextFilesW (CompressedHandle, savedIndex);
  818. }
  819. }
  820. PopError ();
  821. }
  822. return result;
  823. }
  824. BOOL
  825. CompressFlushAndCloseHandleA (
  826. IN OUT PCOMPRESS_HANDLEA CompressedHandle
  827. )
  828. {
  829. CHAR currFile [1024];
  830. PCSTR currFullPath = NULL;
  831. DWORD signature = COMPRESS_SIG;
  832. BOOL result = FALSE;
  833. __try {
  834. if ((CompressedHandle) &&
  835. (CompressedHandle->CurrFileHandle) &&
  836. (CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
  837. ) {
  838. result = CloseHandle (CompressedHandle->CurrFileHandle);
  839. CompressedHandle->CurrFileHandle = NULL;
  840. if (result) {
  841. // write the total number of files compressed into the first file
  842. result = FALSE;
  843. wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->FirstFileIndex);
  844. currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
  845. CompressedHandle->CurrFileHandle = BfOpenFileA (currFullPath);
  846. if ((CompressedHandle->CurrFileHandle == NULL) ||
  847. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  848. ) {
  849. __leave;
  850. }
  851. FreePathStringA (currFullPath);
  852. currFullPath = NULL;
  853. // write again the signature
  854. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  855. __leave;
  856. }
  857. // write number of files compressed
  858. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  859. __leave;
  860. }
  861. result = CloseHandle (CompressedHandle->CurrFileHandle);
  862. CompressedHandle->CurrFileHandle = NULL;
  863. }
  864. }
  865. }
  866. __finally {
  867. PushError ();
  868. if (currFullPath) {
  869. FreePathStringA (currFullPath);
  870. currFullPath = NULL;
  871. }
  872. CompressCleanupHandleA (CompressedHandle);
  873. PopError ();
  874. }
  875. return result;
  876. }
  877. BOOL
  878. CompressFlushAndCloseHandleW (
  879. IN OUT PCOMPRESS_HANDLEW CompressedHandle
  880. )
  881. {
  882. WCHAR currFile [1024];
  883. PCWSTR currFullPath = NULL;
  884. DWORD signature = COMPRESS_SIG;
  885. BOOL result = FALSE;
  886. __try {
  887. if ((CompressedHandle) &&
  888. (CompressedHandle->CurrFileHandle) &&
  889. (CompressedHandle->CurrFileHandle != INVALID_HANDLE_VALUE)
  890. ) {
  891. result = CloseHandle (CompressedHandle->CurrFileHandle);
  892. CompressedHandle->CurrFileHandle = NULL;
  893. if (result) {
  894. // write the total number of files compressed into the first file
  895. result = FALSE;
  896. wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->FirstFileIndex);
  897. currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
  898. CompressedHandle->CurrFileHandle = BfOpenFileW (currFullPath);
  899. if ((CompressedHandle->CurrFileHandle == NULL) ||
  900. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  901. ) {
  902. __leave;
  903. }
  904. FreePathStringW (currFullPath);
  905. currFullPath = NULL;
  906. // write again the signature
  907. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  908. __leave;
  909. }
  910. // write number of files compressed
  911. if (!BfWriteFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  912. __leave;
  913. }
  914. result = CloseHandle (CompressedHandle->CurrFileHandle);
  915. CompressedHandle->CurrFileHandle = NULL;
  916. }
  917. }
  918. }
  919. __finally {
  920. PushError ();
  921. if (currFullPath) {
  922. FreePathStringW (currFullPath);
  923. currFullPath = NULL;
  924. }
  925. CompressCleanupHandleW (CompressedHandle);
  926. PopError ();
  927. }
  928. return result;
  929. }
  930. BOOL
  931. CompressOpenHandleA (
  932. IN PCSTR StorePath,
  933. IN PCSTR MainFilePattern,
  934. IN UINT StartIndex,
  935. OUT PCOMPRESS_HANDLEA CompressedHandle
  936. )
  937. {
  938. CHAR currFile [1024];
  939. PCSTR currFullPath = NULL;
  940. DWORD signature = 0;
  941. BOOL result = FALSE;
  942. __try {
  943. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEA));
  944. if (StartIndex == 0) {
  945. CompressedHandle->CurrFileIndex = 1;
  946. } else {
  947. CompressedHandle->CurrFileIndex = StartIndex;
  948. }
  949. CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
  950. CompressedHandle->StorePath = DuplicatePathStringA (StorePath, 0);
  951. if (!CompressedHandle->StorePath) {
  952. __leave;
  953. }
  954. CompressedHandle->MainFilePattern = DuplicatePathStringA (MainFilePattern, 0);
  955. if (!CompressedHandle->MainFilePattern) {
  956. __leave;
  957. }
  958. wsprintfA (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  959. currFullPath = JoinPathsA (CompressedHandle->StorePath, currFile);
  960. CompressedHandle->CurrFileHandle = BfOpenReadFileA (currFullPath);
  961. if ((CompressedHandle->CurrFileHandle == NULL) ||
  962. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  963. ) {
  964. __leave;
  965. }
  966. FreePathStringA (currFullPath);
  967. currFullPath = NULL;
  968. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  969. __leave;
  970. }
  971. CompressedHandle->CurrFileSize += sizeof (DWORD);
  972. if (signature != COMPRESS_SIG) {
  973. SetLastError (ERROR_INVALID_DATA);
  974. __leave;
  975. }
  976. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  977. __leave;
  978. }
  979. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  980. CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  981. if (!CompressedHandle->ReadBuffer) {
  982. __leave;
  983. }
  984. CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  985. if (!CompressedHandle->CompBuffer) {
  986. __leave;
  987. }
  988. result = TRUE;
  989. }
  990. __finally {
  991. PushError ();
  992. if (currFullPath) {
  993. FreePathStringA (currFullPath);
  994. currFullPath = NULL;
  995. }
  996. if (!result) {
  997. CompressCleanupHandleA (CompressedHandle);
  998. }
  999. PopError ();
  1000. }
  1001. return result;
  1002. }
  1003. BOOL
  1004. CompressOpenHandleW (
  1005. IN PCWSTR StorePath,
  1006. IN PCWSTR MainFilePattern,
  1007. IN UINT StartIndex,
  1008. OUT PCOMPRESS_HANDLEW CompressedHandle
  1009. )
  1010. {
  1011. WCHAR currFile [1024];
  1012. PCWSTR currFullPath = NULL;
  1013. DWORD signature = 0;
  1014. BOOL result = FALSE;
  1015. __try {
  1016. ZeroMemory (CompressedHandle, sizeof (COMPRESS_HANDLEW));
  1017. if (StartIndex == 0) {
  1018. CompressedHandle->CurrFileIndex = 1;
  1019. } else {
  1020. CompressedHandle->CurrFileIndex = StartIndex;
  1021. }
  1022. CompressedHandle->FirstFileIndex = CompressedHandle->CurrFileIndex;
  1023. CompressedHandle->StorePath = DuplicatePathStringW (StorePath, 0);
  1024. if (!CompressedHandle->StorePath) {
  1025. __leave;
  1026. }
  1027. CompressedHandle->MainFilePattern = DuplicatePathStringW (MainFilePattern, 0);
  1028. if (!CompressedHandle->MainFilePattern) {
  1029. __leave;
  1030. }
  1031. wsprintfW (currFile, CompressedHandle->MainFilePattern, CompressedHandle->CurrFileIndex);
  1032. currFullPath = JoinPathsW (CompressedHandle->StorePath, currFile);
  1033. CompressedHandle->CurrFileHandle = BfOpenReadFileW (currFullPath);
  1034. if ((CompressedHandle->CurrFileHandle == NULL) ||
  1035. (CompressedHandle->CurrFileHandle == INVALID_HANDLE_VALUE)
  1036. ) {
  1037. __leave;
  1038. }
  1039. FreePathStringW (currFullPath);
  1040. currFullPath = NULL;
  1041. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  1042. __leave;
  1043. }
  1044. CompressedHandle->CurrFileSize += sizeof (DWORD);
  1045. if (signature != COMPRESS_SIG) {
  1046. SetLastError (ERROR_INVALID_DATA);
  1047. __leave;
  1048. }
  1049. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&CompressedHandle->FilesStored), sizeof (LONGLONG))) {
  1050. __leave;
  1051. }
  1052. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  1053. CompressedHandle->ReadBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  1054. if (!CompressedHandle->ReadBuffer) {
  1055. __leave;
  1056. }
  1057. CompressedHandle->CompBuffer = MemAlloc (g_hHeap, 0, COMPRESS_BUFFER_SIZE + 2 * sizeof (USHORT));
  1058. if (!CompressedHandle->CompBuffer) {
  1059. __leave;
  1060. }
  1061. result = TRUE;
  1062. }
  1063. __finally {
  1064. PushError ();
  1065. if (currFullPath) {
  1066. FreePathStringW (currFullPath);
  1067. currFullPath = NULL;
  1068. }
  1069. if (!result) {
  1070. CompressCleanupHandleW (CompressedHandle);
  1071. }
  1072. PopError ();
  1073. }
  1074. return result;
  1075. }
  1076. BOOL
  1077. CompressExtractAllFilesA (
  1078. IN PCSTR ExtractPath,
  1079. IN OUT PCOMPRESS_HANDLEA CompressedHandle,
  1080. IN PCOMPRESSNOTIFICATIONA CompressNotification OPTIONAL
  1081. )
  1082. {
  1083. DWORD signature;
  1084. LONGLONG fileSize;
  1085. LONGLONG fileSizeRead;
  1086. DWORD fileNameSize;
  1087. PCWSTR storedName = NULL;
  1088. PCSTR storedNameA = NULL;
  1089. PCSTR extractPath = NULL;
  1090. PCSTR newFileName = NULL;
  1091. BOOL extractFile = TRUE;
  1092. HANDLE extractHandle = NULL;
  1093. USHORT compType = 0;
  1094. USHORT compSize = 0;
  1095. DWORD bytesComp;
  1096. LARGE_INTEGER savedSize;
  1097. BOOL result = FALSE;
  1098. __try {
  1099. for (;;) {
  1100. // read the header for this file
  1101. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  1102. // It is possible that we continue onto the next file, let's try that.
  1103. if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
  1104. result = TRUE;
  1105. __leave;
  1106. }
  1107. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  1108. __leave;
  1109. }
  1110. }
  1111. CompressedHandle->CurrFileSize += sizeof (DWORD);
  1112. if (signature != COMPRESS_NEWFILE) {
  1113. SetLastError (ERROR_INVALID_DATA);
  1114. __leave;
  1115. }
  1116. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
  1117. __leave;
  1118. }
  1119. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  1120. fileSizeRead = 0;
  1121. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
  1122. __leave;
  1123. }
  1124. CompressedHandle->CurrFileSize += sizeof (DWORD);
  1125. storedName = MemAlloc (g_hHeap, 0, fileNameSize);
  1126. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(storedName), fileNameSize)) {
  1127. __leave;
  1128. }
  1129. CompressedHandle->CurrFileSize += fileNameSize;
  1130. storedNameA = ConvertWtoA (storedName);
  1131. if (!storedNameA) {
  1132. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  1133. __leave;
  1134. }
  1135. extractPath = JoinPathsA (ExtractPath, storedNameA);
  1136. if (!extractPath) {
  1137. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  1138. __leave;
  1139. }
  1140. extractFile = TRUE;
  1141. newFileName = NULL;
  1142. if (CompressNotification) {
  1143. if (!CompressNotification (extractPath, fileSize, &extractFile, &newFileName)) {
  1144. __leave;
  1145. }
  1146. }
  1147. if (extractFile) {
  1148. if (newFileName) {
  1149. // let's make sure that the directory exists
  1150. BfCreateDirectoryExA (newFileName, FALSE);
  1151. }
  1152. extractHandle = BfCreateFileA (newFileName?newFileName:extractPath);
  1153. if ((extractHandle == NULL) ||
  1154. (extractHandle == INVALID_HANDLE_VALUE)
  1155. ) {
  1156. __leave;
  1157. }
  1158. } else {
  1159. extractHandle = NULL;
  1160. }
  1161. if (newFileName) {
  1162. FreePathStringA (newFileName);
  1163. newFileName = NULL;
  1164. }
  1165. FreePathStringA (extractPath);
  1166. extractPath = NULL;
  1167. MemFree (g_hHeap, 0, storedName);
  1168. storedName = NULL;
  1169. FreeConvertedStr (storedNameA);
  1170. storedNameA = NULL;
  1171. if (fileSize > 0) {
  1172. if (!extractFile && g_ErrorMode) {
  1173. for (;;) {
  1174. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1175. // It is possible that we continue onto the next file, let's try that.
  1176. if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
  1177. // we might be at the end of the compressed file, there are no other files here
  1178. result = TRUE;
  1179. __leave;
  1180. }
  1181. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1182. __leave;
  1183. }
  1184. }
  1185. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1186. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
  1187. __leave;
  1188. }
  1189. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1190. // let's try to see if we just read a new file signature
  1191. *((PUSHORT)(&signature) + 0) = compType;
  1192. *((PUSHORT)(&signature) + 1) = compSize;
  1193. if (signature == COMPRESS_NEWFILE) {
  1194. // this is a new file
  1195. CompressedHandle->CurrFileSize -= sizeof (USHORT);
  1196. CompressedHandle->CurrFileSize -= sizeof (USHORT);
  1197. // rewind the file current pointer;
  1198. savedSize.QuadPart = CompressedHandle->CurrFileSize;
  1199. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  1200. // we are done with the current file
  1201. break;
  1202. } else {
  1203. // Let's advance the file pointer
  1204. if (SetFilePointer (CompressedHandle->CurrFileHandle, compSize, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) {
  1205. __leave;
  1206. }
  1207. CompressedHandle->CurrFileSize += compSize;
  1208. }
  1209. }
  1210. } else {
  1211. for (;;) {
  1212. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1213. // It is possible that we continue onto the next file, let's try that.
  1214. if (!pPrepareNextFileA (CompressedHandle, TRUE)) {
  1215. __leave;
  1216. }
  1217. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1218. __leave;
  1219. }
  1220. }
  1221. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1222. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
  1223. __leave;
  1224. }
  1225. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1226. if (!BfReadFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
  1227. __leave;
  1228. }
  1229. CompressedHandle->CurrFileSize += compSize;
  1230. if (compType == CompressNone) {
  1231. if (extractFile) {
  1232. if (!BfWriteFile (extractHandle, CompressedHandle->CompBuffer, compSize)) {
  1233. __leave;
  1234. }
  1235. }
  1236. fileSizeRead += compSize;
  1237. } else {
  1238. bytesComp = DecompressData (
  1239. compType,
  1240. CompressedHandle->CompBuffer,
  1241. compSize,
  1242. CompressedHandle->ReadBuffer,
  1243. COMPRESS_BUFFER_SIZE
  1244. );
  1245. if (bytesComp > COMPRESS_BUFFER_SIZE) {
  1246. SetLastError (ERROR_INVALID_DATA);
  1247. __leave;
  1248. }
  1249. if (extractFile) {
  1250. if (!BfWriteFile (extractHandle, CompressedHandle->ReadBuffer, bytesComp)) {
  1251. __leave;
  1252. }
  1253. }
  1254. fileSizeRead += bytesComp;
  1255. }
  1256. if (fileSizeRead == fileSize) {
  1257. // this file is done, let's go to the next one
  1258. break;
  1259. }
  1260. }
  1261. }
  1262. }
  1263. if (extractHandle) {
  1264. CloseHandle (extractHandle);
  1265. extractHandle = NULL;
  1266. }
  1267. }
  1268. }
  1269. __finally {
  1270. if (storedName != NULL) {
  1271. MemFree (g_hHeap, 0, storedName);
  1272. storedName = NULL;
  1273. }
  1274. if (storedNameA != NULL) {
  1275. FreeConvertedStr (storedNameA);
  1276. storedNameA = NULL;
  1277. }
  1278. if (newFileName != NULL) {
  1279. FreePathStringA (newFileName);
  1280. newFileName = NULL;
  1281. }
  1282. if (extractPath != NULL) {
  1283. FreePathStringA (extractPath);
  1284. extractPath = NULL;
  1285. }
  1286. if ((extractHandle != NULL) &&
  1287. (extractHandle != INVALID_HANDLE_VALUE)
  1288. ) {
  1289. CloseHandle (extractHandle);
  1290. extractHandle = NULL;
  1291. }
  1292. }
  1293. return result;
  1294. }
  1295. BOOL
  1296. CompressExtractAllFilesW (
  1297. IN PCWSTR ExtractPath,
  1298. IN OUT PCOMPRESS_HANDLEW CompressedHandle,
  1299. IN PCOMPRESSNOTIFICATIONW CompressNotification OPTIONAL
  1300. )
  1301. {
  1302. DWORD signature;
  1303. LONGLONG fileSize;
  1304. LONGLONG fileSizeRead;
  1305. DWORD fileNameSize;
  1306. PCWSTR storedName = NULL;
  1307. PCWSTR extractPath = NULL;
  1308. PCWSTR newFileName = NULL;
  1309. BOOL extractFile = TRUE;
  1310. HANDLE extractHandle = NULL;
  1311. USHORT compType = 0;
  1312. USHORT compSize = 0;
  1313. DWORD bytesComp;
  1314. LARGE_INTEGER savedSize;
  1315. BOOL result = FALSE;
  1316. __try {
  1317. for (;;) {
  1318. // read the header for this file
  1319. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  1320. // It is possible that we continue onto the next file, let's try that.
  1321. if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
  1322. result = TRUE;
  1323. __leave;
  1324. }
  1325. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  1326. __leave;
  1327. }
  1328. }
  1329. CompressedHandle->CurrFileSize += sizeof (DWORD);
  1330. if (signature != COMPRESS_NEWFILE) {
  1331. SetLastError (ERROR_INVALID_DATA);
  1332. __leave;
  1333. }
  1334. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileSize), sizeof (LONGLONG))) {
  1335. __leave;
  1336. }
  1337. CompressedHandle->CurrFileSize += sizeof (LONGLONG);
  1338. fileSizeRead = 0;
  1339. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&fileNameSize), sizeof (DWORD))) {
  1340. __leave;
  1341. }
  1342. CompressedHandle->CurrFileSize += sizeof (DWORD);
  1343. storedName = MemAlloc (g_hHeap, 0, fileNameSize);
  1344. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(storedName), fileNameSize)) {
  1345. __leave;
  1346. }
  1347. CompressedHandle->CurrFileSize += fileNameSize;
  1348. extractPath = JoinPathsW (ExtractPath, storedName);
  1349. if (!extractPath) {
  1350. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  1351. __leave;
  1352. }
  1353. extractFile = TRUE;
  1354. newFileName = NULL;
  1355. if (CompressNotification) {
  1356. if (!CompressNotification (extractPath, fileSize, &extractFile, &newFileName)) {
  1357. __leave;
  1358. }
  1359. }
  1360. if (extractFile) {
  1361. if (newFileName) {
  1362. // let's make sure that the directory exists
  1363. BfCreateDirectoryExW (newFileName, FALSE);
  1364. }
  1365. extractHandle = BfCreateFileW (newFileName?newFileName:extractPath);
  1366. if ((extractHandle == NULL) ||
  1367. (extractHandle == INVALID_HANDLE_VALUE)
  1368. ) {
  1369. __leave;
  1370. }
  1371. } else {
  1372. extractHandle = NULL;
  1373. }
  1374. if (newFileName) {
  1375. FreePathStringW (newFileName);
  1376. newFileName = NULL;
  1377. }
  1378. FreePathStringW (extractPath);
  1379. extractPath = NULL;
  1380. MemFree (g_hHeap, 0, storedName);
  1381. storedName = NULL;
  1382. if (fileSize) {
  1383. if (!extractFile && g_ErrorMode) {
  1384. for (;;) {
  1385. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1386. // It is possible that we continue onto the next file, let's try that.
  1387. if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
  1388. // we might be at the end of the compressed file, there are no other files here
  1389. result = TRUE;
  1390. __leave;
  1391. }
  1392. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1393. __leave;
  1394. }
  1395. }
  1396. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1397. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
  1398. __leave;
  1399. }
  1400. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1401. // let's try to see if we just read a new file signature
  1402. *((PUSHORT)(&signature + 0)) = compType;
  1403. *((PUSHORT)(&signature + 1)) = compSize;
  1404. if (signature == COMPRESS_NEWFILE) {
  1405. // this is a new file
  1406. CompressedHandle->CurrFileSize -= sizeof (USHORT);
  1407. CompressedHandle->CurrFileSize -= sizeof (USHORT);
  1408. // rewind the file current pointer;
  1409. savedSize.QuadPart = CompressedHandle->CurrFileSize;
  1410. SetFilePointer (CompressedHandle->CurrFileHandle, savedSize.LowPart, &(savedSize.HighPart), FILE_BEGIN);
  1411. // we are done with the current file
  1412. break;
  1413. } else {
  1414. // Let's advance the file pointer
  1415. if (SetFilePointer (CompressedHandle->CurrFileHandle, compSize, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) {
  1416. __leave;
  1417. }
  1418. CompressedHandle->CurrFileSize += compSize;
  1419. }
  1420. }
  1421. } else {
  1422. for (;;) {
  1423. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1424. // It is possible that we continue onto the next file, let's try that.
  1425. if (!pPrepareNextFileW (CompressedHandle, TRUE)) {
  1426. __leave;
  1427. }
  1428. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compType), sizeof (USHORT))) {
  1429. __leave;
  1430. }
  1431. }
  1432. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1433. if (!BfReadFile (CompressedHandle->CurrFileHandle, (PBYTE)(&compSize), sizeof (USHORT))) {
  1434. __leave;
  1435. }
  1436. CompressedHandle->CurrFileSize += sizeof (USHORT);
  1437. if (!BfReadFile (CompressedHandle->CurrFileHandle, CompressedHandle->CompBuffer, compSize)) {
  1438. __leave;
  1439. }
  1440. CompressedHandle->CurrFileSize += compSize;
  1441. if (compType == CompressNone) {
  1442. if (extractFile) {
  1443. if (!BfWriteFile (extractHandle, CompressedHandle->CompBuffer, compSize)) {
  1444. __leave;
  1445. }
  1446. }
  1447. fileSizeRead += compSize;
  1448. } else {
  1449. bytesComp = DecompressData (
  1450. compType,
  1451. CompressedHandle->CompBuffer,
  1452. compSize,
  1453. CompressedHandle->ReadBuffer,
  1454. COMPRESS_BUFFER_SIZE
  1455. );
  1456. if (bytesComp > COMPRESS_BUFFER_SIZE) {
  1457. SetLastError (ERROR_INVALID_DATA);
  1458. __leave;
  1459. }
  1460. if (extractFile) {
  1461. if (!BfWriteFile (extractHandle, CompressedHandle->ReadBuffer, bytesComp)) {
  1462. __leave;
  1463. }
  1464. }
  1465. fileSizeRead += bytesComp;
  1466. }
  1467. if (fileSizeRead == fileSize) {
  1468. // this file is done, let's go to the next one
  1469. break;
  1470. }
  1471. }
  1472. }
  1473. }
  1474. if (extractHandle) {
  1475. CloseHandle (extractHandle);
  1476. extractHandle = NULL;
  1477. }
  1478. }
  1479. }
  1480. __finally {
  1481. if (storedName != NULL) {
  1482. MemFree (g_hHeap, 0, storedName);
  1483. storedName = NULL;
  1484. }
  1485. if (newFileName != NULL) {
  1486. FreePathStringW (newFileName);
  1487. newFileName = NULL;
  1488. }
  1489. if (extractPath != NULL) {
  1490. FreePathStringW (extractPath);
  1491. extractPath = NULL;
  1492. }
  1493. if ((extractHandle != NULL) &&
  1494. (extractHandle != INVALID_HANDLE_VALUE)
  1495. ) {
  1496. CloseHandle (extractHandle);
  1497. extractHandle = NULL;
  1498. }
  1499. }
  1500. return result;
  1501. }
  1502. BOOL
  1503. CompressSetErrorMode (
  1504. IN BOOL ErrorMode
  1505. )
  1506. {
  1507. BOOL oldErrorMode = g_ErrorMode;
  1508. g_ErrorMode = ErrorMode;
  1509. return oldErrorMode;
  1510. }