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.

612 lines
14 KiB

  1. /*++
  2. Module Name:
  3. diamond.c
  4. Abstract:
  5. Diamond compression interface.
  6. This module contains functions to compress a file using
  7. the mszip compression library.
  8. Author:
  9. Ted Miller
  10. Environment:
  11. Windows
  12. --*/
  13. #include <io.h>
  14. #include <fcntl.h>
  15. #include <errno.h>
  16. //#include "main.h"
  17. //#include <diamondc.h>
  18. //#include "mydiam.h"
  19. #include "pch.h"
  20. CHAR MakeCompressedName( LPSTR );
  21. typedef struct _DIAMOND_INFO {
  22. DWORD SourceFileSize;
  23. DWORD CompressedSize;
  24. FILETIME SourceFileCreationTime;
  25. FILETIME SourceFileModifiedTime;
  26. FILETIME SourceFileAccessedTime;
  27. } DIAMOND_INFO, *PDIAMOND_INFO;
  28. //
  29. // Callback functions to perform memory allocation, io, etc.
  30. // We pass addresses of these functions to diamond.
  31. //
  32. int
  33. DIAMONDAPI
  34. fciFilePlacedCB(
  35. OUT PCCAB Cabinet,
  36. IN LPSTR FileName,
  37. IN LONG FileSize,
  38. IN BOOL Continuation,
  39. IN PVOID Context
  40. )
  41. /*++
  42. Routine Description:
  43. Callback used by diamond to indicate that a file has been
  44. comitted to a cabinet.
  45. No action is taken and success is returned.
  46. Arguments:
  47. Cabinet - cabinet structure to fill in.
  48. FileName - name of file in cabinet
  49. FileSize - size of file in cabinet
  50. Continuation - TRUE if this is a partial file, continuation
  51. of compression begun in a different cabinet.
  52. Context - supplies context information.
  53. Return Value:
  54. 0 (success).
  55. --*/
  56. {
  57. UNREFERENCED_PARAMETER(Cabinet);
  58. UNREFERENCED_PARAMETER(FileName);
  59. UNREFERENCED_PARAMETER(FileSize);
  60. UNREFERENCED_PARAMETER(Continuation);
  61. UNREFERENCED_PARAMETER(Context);
  62. return(0);
  63. }
  64. PVOID
  65. DIAMONDAPI
  66. fciAllocCB(
  67. IN ULONG NumberOfBytes
  68. )
  69. /*++
  70. Routine Description:
  71. Callback used by diamond to allocate memory.
  72. Arguments:
  73. NumberOfBytes - supplies desired size of block.
  74. Return Value:
  75. Returns pointer to a block of memory or NULL
  76. if memory cannot be allocated.
  77. --*/
  78. {
  79. return((PVOID)LocalAlloc(LMEM_FIXED,NumberOfBytes));
  80. }
  81. VOID
  82. DIAMONDAPI
  83. fciFreeCB(
  84. IN PVOID Block
  85. )
  86. /*++
  87. Routine Description:
  88. Callback used by diamond to free a memory block.
  89. The block must have been allocated with fciAlloc().
  90. Arguments:
  91. Block - supplies pointer to block of memory to be freed.
  92. Return Value:
  93. None.
  94. --*/
  95. {
  96. LocalFree((HLOCAL)Block);
  97. }
  98. FNFCIGETTEMPFILE(fciTempFileCB)
  99. {
  100. CHAR TempPath[MAX_PATH];
  101. DWORD cchTemp;
  102. cchTemp = GetTempPathA(sizeof(TempPath),TempPath);
  103. if ((cchTemp == 0) || (cchTemp >= sizeof(TempPath))) {
  104. TempPath[0] = '.';
  105. TempPath[1] = '\0';
  106. }
  107. if(GetTempFileNameA(TempPath,"dc",0,pszTempName)) {
  108. DeleteFileA(pszTempName);
  109. }
  110. return(TRUE);
  111. }
  112. BOOL
  113. DIAMONDAPI
  114. fciNextCabinetCB(
  115. OUT PCCAB Cabinet,
  116. IN DWORD CabinetSizeEstimate,
  117. IN PVOID Context
  118. )
  119. /*++
  120. Routine Description:
  121. Callback used by diamond to request a new cabinet file.
  122. This functionality is not used in our implementation as
  123. we deal only with single-file cabinets.
  124. Arguments:
  125. Cabinet - cabinet structure to be filled in.
  126. CabinetSizeEstimate - estimated size of cabinet.
  127. Context - supplies context information.
  128. Return Value:
  129. FALSE (failure).
  130. --*/
  131. {
  132. UNREFERENCED_PARAMETER(Cabinet);
  133. UNREFERENCED_PARAMETER(CabinetSizeEstimate);
  134. UNREFERENCED_PARAMETER(Context);
  135. return(FALSE);
  136. }
  137. BOOL
  138. DIAMONDAPI
  139. fciStatusCB(
  140. IN UINT StatusType,
  141. IN DWORD Count1,
  142. IN DWORD Count2,
  143. IN PVOID Context
  144. )
  145. /*++
  146. Routine Description:
  147. Callback used by diamond to give status on file compression
  148. and cabinet operations, etc.
  149. Arguments:
  150. Status Type - supplies status type.
  151. 0 = statusFile - compressing block into a folder.
  152. Count1 = compressed size
  153. Count2 = uncompressed size
  154. 1 = statusFolder - performing AddFilder.
  155. Count1 = bytes done
  156. Count2 = total bytes
  157. Context - supplies context info.
  158. Return Value:
  159. TRUE (success).
  160. --*/
  161. {
  162. PDIAMOND_INFO context;
  163. UNREFERENCED_PARAMETER(Count2);
  164. context = (PDIAMOND_INFO)Context;
  165. if(StatusType == statusFile) {
  166. //
  167. // Track compressed size.
  168. //
  169. context->CompressedSize += Count1;
  170. }
  171. return(TRUE);
  172. }
  173. FNFCIGETOPENINFO(fciOpenInfoCB)
  174. {
  175. int h;
  176. WIN32_FIND_DATAA FindData;
  177. HANDLE FindHandle;
  178. PDIAMOND_INFO context;
  179. FILETIME ftLocal;
  180. context = pv;
  181. FindHandle = FindFirstFileA(pszName,&FindData);
  182. if(FindHandle == INVALID_HANDLE_VALUE) {
  183. return(-1);
  184. }
  185. FindClose(FindHandle);
  186. context->SourceFileSize = FindData.nFileSizeLow;
  187. context->SourceFileCreationTime = FindData.ftCreationTime;
  188. context->SourceFileModifiedTime = FindData.ftLastWriteTime;
  189. context->SourceFileAccessedTime = FindData.ftLastAccessTime;
  190. FileTimeToLocalFileTime(&FindData.ftLastWriteTime, &ftLocal);
  191. FileTimeToDosDateTime(&ftLocal, pdate, ptime);
  192. *pattribs = (WORD)(FindData.dwFileAttributes &
  193. ( FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
  194. FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE ));
  195. h = _open(pszName,_O_RDONLY | _O_BINARY);
  196. if(h == -1) {
  197. return(-1);
  198. }
  199. return(h);
  200. }
  201. FNFCIOPEN(fciOpen)
  202. {
  203. int result;
  204. result = _open(pszFile, oflag, pmode);
  205. if (result == -1) {
  206. *err = errno;
  207. }
  208. return(result);
  209. }
  210. FNFCIREAD(fciRead)
  211. {
  212. UINT result;
  213. result = (UINT) _read((HFILE)hf, memory, cb);
  214. if (result != cb) {
  215. *err = errno;
  216. }
  217. return(result);
  218. }
  219. FNFCIWRITE(fciWrite)
  220. {
  221. UINT result;
  222. result = (UINT) _write((HFILE)hf, memory, cb);
  223. if (result != cb) {
  224. *err = errno;
  225. }
  226. return(result);
  227. }
  228. FNFCICLOSE(fciClose)
  229. {
  230. int result;
  231. result = _close((HFILE)hf);
  232. if (result == -1) {
  233. *err = errno;
  234. }
  235. return(result);
  236. }
  237. FNFCISEEK(fciSeek)
  238. {
  239. long result;
  240. result = _lseek((HFILE)hf, dist, seektype);
  241. if (result == -1) {
  242. *err = errno;
  243. }
  244. return(result);
  245. }
  246. FNFCIDELETE(fciDelete)
  247. {
  248. int result;
  249. result = _unlink(pszFile);
  250. if (result == -1) {
  251. *err = errno;
  252. }
  253. return(result);
  254. }
  255. INT
  256. DiamondCompressFile(
  257. IN NOTIFYPROC CompressNotify,
  258. IN LPSTR SourceFile,
  259. IN LPSTR TargetFile,
  260. IN BOOL Rename,
  261. OUT PLZINFO pLZI
  262. )
  263. {
  264. BOOL b;
  265. LPSTR SourceFilenamePart,p;
  266. HFCI FciContext;
  267. ERF FciError;
  268. CCAB ccab;
  269. CHAR targetFile[MAX_PATH];
  270. WCHAR wszSourceFile[MAX_PATH] = NULL_STRING;
  271. WCHAR wszTargetFile[MAX_PATH] = NULL_STRING;
  272. DIAMOND_INFO Context;
  273. INT Status;
  274. __try {
  275. //
  276. // Isolate the filename part of the source file.
  277. //
  278. if(SourceFilenamePart = strrchr(SourceFile, '\\')) {
  279. SourceFilenamePart++;
  280. } else {
  281. SourceFilenamePart = SourceFile;
  282. }
  283. //
  284. // Form the actual name of the target file.
  285. //
  286. strcpy(targetFile,TargetFile);
  287. if(Rename) {
  288. MakeCompressedName(targetFile);
  289. }
  290. //
  291. // Fill in the cabinet structure.
  292. //
  293. ZeroMemory(&ccab,sizeof(ccab));
  294. lstrcpyA(ccab.szCabPath, targetFile);
  295. if(p=strrchr(ccab.szCabPath,'\\')) {
  296. lstrcpyA(ccab.szCab,++p);
  297. *p = 0;
  298. } else {
  299. lstrcpyA(ccab.szCab,targetFile);
  300. ccab.szCabPath[0] = 0;
  301. }
  302. //
  303. // Call the notification function to see whether we are really
  304. // supposed to compress this file.
  305. //
  306. MultiByteToWideChar( CP_THREAD_ACP, 0, SourceFile, strlen(SourceFile), wszSourceFile, MAX_PATH );
  307. MultiByteToWideChar( CP_THREAD_ACP, 0, targetFile, strlen(targetFile), wszTargetFile, MAX_PATH );
  308. if(!CompressNotify(wszSourceFile,wszTargetFile,NOTIFY_START_COMPRESS)) {
  309. Status = BLANK_ERROR;
  310. __leave;
  311. }
  312. ZeroMemory(&Context,sizeof(Context));
  313. //
  314. // Compress the file.
  315. //
  316. FciContext = FCICreate(
  317. &FciError,
  318. fciFilePlacedCB,
  319. fciAllocCB,
  320. fciFreeCB,
  321. fciOpen,
  322. fciRead,
  323. fciWrite,
  324. fciClose,
  325. fciSeek,
  326. fciDelete,
  327. fciTempFileCB,
  328. &ccab,
  329. &Context
  330. );
  331. if(FciContext) {
  332. b = FCIAddFile(
  333. FciContext,
  334. SourceFile, // file to add to cabinet.
  335. SourceFilenamePart, // filename part, name to store in cabinet.
  336. FALSE,
  337. fciNextCabinetCB, // routine for next cabinet (always fails)
  338. fciStatusCB,
  339. fciOpenInfoCB,
  340. DiamondCompressionType
  341. );
  342. if(b) {
  343. b = FCIFlushCabinet(
  344. FciContext,
  345. FALSE,
  346. fciNextCabinetCB,
  347. fciStatusCB
  348. );
  349. if(b) {
  350. HANDLE FindHandle;
  351. WIN32_FIND_DATA FindData;
  352. //
  353. // Context.CompressedSize does not include headers
  354. // and any other file overhead.
  355. //
  356. FindHandle = FindFirstFile((LPCWSTR)targetFile,&FindData);
  357. if(FindHandle == INVALID_HANDLE_VALUE) {
  358. pLZI->cblOutSize = (LONG)Context.CompressedSize;
  359. } else {
  360. pLZI->cblOutSize = (LONG)FindData.nFileSizeLow;
  361. FindClose(FindHandle);
  362. }
  363. pLZI->cblInSize = (LONG)Context.SourceFileSize;
  364. FindHandle = CreateFile((LPWSTR)targetFile,
  365. GENERIC_READ | GENERIC_WRITE,
  366. 0,
  367. NULL,
  368. OPEN_EXISTING,
  369. 0,
  370. NULL);
  371. if (FindHandle != INVALID_HANDLE_VALUE)
  372. {
  373. SetFileTime(FindHandle,
  374. &Context.SourceFileCreationTime,
  375. &Context.SourceFileAccessedTime,
  376. &Context.SourceFileModifiedTime);
  377. CloseHandle(FindHandle);
  378. }
  379. }
  380. }
  381. if(b) {
  382. Status = TRUE;
  383. } else {
  384. switch(FciError.erfOper) {
  385. case FCIERR_OPEN_SRC:
  386. Status = LZERROR_BADINHANDLE;
  387. break;
  388. case FCIERR_READ_SRC:
  389. Status = LZERROR_READ;
  390. break;
  391. case FCIERR_CAB_FILE:
  392. Status = LZERROR_WRITE;
  393. break;
  394. case FCIERR_ALLOC_FAIL:
  395. Status = LZERROR_GLOBALLOC;
  396. break;
  397. case FCIERR_TEMP_FILE:
  398. case FCIERR_BAD_COMPR_TYPE:
  399. case FCIERR_USER_ABORT:
  400. case FCIERR_MCI_FAIL:
  401. default:
  402. Status = FALSE;
  403. }
  404. }
  405. FCIDestroy(FciContext);
  406. } else {
  407. Status = LZERROR_GLOBALLOC;
  408. }
  409. } __except(EXCEPTION_EXECUTE_HANDLER) {
  410. Status = GetLastError();
  411. }
  412. return(Status);
  413. }
  414. CHAR MakeCompressedName(CHAR ARG_PTR *pszFileName)
  415. {
  416. CHAR chReplaced = '\0';
  417. ULONG NameLength = strlen( pszFileName );
  418. ULONG DotIndex = NameLength;
  419. while (( DotIndex > 0 ) && ( pszFileName[ --DotIndex ] != '.' )) {
  420. if (( pszFileName[ DotIndex ] == '\\' ) ||
  421. ( pszFileName[ DotIndex ] == ':' )) { // end of filename part of path
  422. DotIndex = 0; // name has no extension
  423. break;
  424. }
  425. }
  426. if ( DotIndex > 0 ) { // name has an extension
  427. if (( NameLength - DotIndex ) <= 3 ) { // extension less than 3 chars
  428. pszFileName[ NameLength++ ] = '_'; // append '_' to extension
  429. pszFileName[ NameLength ] = 0; // terminate
  430. }
  431. else { // extension more than 3 chars
  432. chReplaced = pszFileName[ NameLength - 1 ]; // return original
  433. pszFileName[ NameLength - 1 ] = '_'; // replace last char with '_'
  434. }
  435. }
  436. else { // name has no extension
  437. pszFileName[ NameLength++ ] = '.'; // append '.'
  438. pszFileName[ NameLength++ ] = '_'; // append '_'
  439. pszFileName[ NameLength ] = 0; // terminate
  440. }
  441. return(chReplaced);
  442. }