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.

563 lines
12 KiB

  1. #include "stdafx.h"
  2. #include "Compress.h"
  3. char cCabName [MAX_PATH];
  4. char CabPath[256];
  5. ULONG g_CompressedPercentage=0;
  6. BOOL g_CancelCompression = FALSE;
  7. /*
  8. * Memory allocation function
  9. */
  10. FNFCIALLOC(mem_alloc)
  11. {
  12. return malloc(cb);
  13. }
  14. /*
  15. * Memory free function
  16. */
  17. FNFCIFREE(mem_free)
  18. {
  19. free(memory);
  20. }
  21. /*
  22. * File i/o functions
  23. */
  24. FNFCIOPEN(fci_open)
  25. {
  26. int result;
  27. result = _open(pszFile, oflag, pmode);
  28. if (result == -1)
  29. *err = errno;
  30. return result;
  31. }
  32. FNFCIREAD(fci_read)
  33. {
  34. unsigned int result;
  35. result = (unsigned int) _read((int)hf, memory, cb);
  36. if (result != cb)
  37. *err = errno;
  38. return result;
  39. }
  40. FNFCIWRITE(fci_write)
  41. {
  42. unsigned int result;
  43. result = (unsigned int) _write((int)hf, memory, cb);
  44. if (result != cb)
  45. *err = errno;
  46. return result;
  47. }
  48. FNFCICLOSE(fci_close)
  49. {
  50. int result;
  51. result = _close((int)hf);
  52. if (result != 0)
  53. *err = errno;
  54. return result;
  55. }
  56. FNFCISEEK(fci_seek)
  57. {
  58. long result;
  59. result = _lseek((int)hf, dist, seektype);
  60. if (result == -1)
  61. *err = errno;
  62. return result;
  63. }
  64. FNFCIDELETE(fci_delete)
  65. {
  66. int result;
  67. result = remove(pszFile);
  68. if (result != 0)
  69. *err = errno;
  70. return result;
  71. }
  72. /*
  73. * File placed function called when a file has been committed
  74. * to a cabinet
  75. */
  76. FNFCIFILEPLACED(file_placed)
  77. {
  78. /*printf(
  79. " placed file '%s' (size %d) on cabinet '%s'\n",
  80. pszFile,
  81. cbFile,
  82. pccab->szCab
  83. );
  84. if (fContinuation)
  85. printf(" (Above file is a later segment of a continued file)\n");
  86. */
  87. return 0;
  88. }
  89. /*
  90. * Function to obtain temporary files
  91. */
  92. FNFCIGETTEMPFILE(get_temp_file)
  93. {
  94. char *psz;
  95. psz = _tempnam("","xx"); // Get a name
  96. if ((psz != NULL) && (strlen(psz) < (unsigned)cbTempName)) {
  97. strcpy(pszTempName,psz); // Copy to caller's buffer
  98. free(psz); // Free temporary name buffer
  99. return TRUE; // Success
  100. }
  101. //** Failed
  102. if (psz) {
  103. free(psz);
  104. }
  105. return FALSE;
  106. }
  107. /*
  108. * Progress function
  109. */
  110. FNFCISTATUS(progress)
  111. {
  112. client_state *cs;
  113. cs = (client_state *) pv;
  114. if (typeStatus == statusFile)
  115. {
  116. cs->total_compressed_size += cb1;
  117. cs->total_uncompressed_size += cb2;
  118. /*
  119. * Compressing a block into a folder
  120. *
  121. * cb2 = uncompressed size of block
  122. */
  123. /* printf(
  124. "Compressing: %9ld -> %9ld \r",
  125. cs->total_uncompressed_size,
  126. cs->total_compressed_size
  127. );
  128. fflush(stdout);
  129. */
  130. g_CompressedPercentage
  131. = get_percentage(cs->total_uncompressed_size,cs->start_uncompressed_size);
  132. }
  133. else if (typeStatus == statusFolder)
  134. {
  135. int percentage;
  136. /*
  137. * Adding a folder to a cabinet
  138. *
  139. * cb1 = amount of folder copied to cabinet so far
  140. * cb2 = total size of folder
  141. */
  142. percentage = get_percentage(cb1, cb2);
  143. cs->start_uncompressed_size = cb2;
  144. // printf("Copying folder to cabinet: %d%% \r", percentage);
  145. fflush(stdout);
  146. }
  147. if (g_CancelCompression)
  148. {
  149. // Abort the compression
  150. return -1;
  151. }
  152. return 0;
  153. }
  154. void store_cab_name(char *cabname, int iCab)
  155. {
  156. sprintf(cabname, cCabName, iCab);
  157. }
  158. FNFCIGETNEXTCABINET(get_next_cabinet)
  159. {
  160. /*
  161. * Cabinet counter has been incremented already by FCI
  162. */
  163. /*
  164. * Store next cabinet name
  165. */
  166. store_cab_name(pccab->szCab, pccab->iCab);
  167. /*
  168. * You could change the disk name here too, if you wanted
  169. */
  170. return TRUE;
  171. }
  172. FNFCIGETOPENINFO(get_open_info)
  173. {
  174. BY_HANDLE_FILE_INFORMATION finfo;
  175. FILETIME filetime;
  176. HANDLE handle;
  177. DWORD attrs;
  178. int hf;
  179. client_state *cs;
  180. cs = (client_state *) pv;
  181. /*
  182. * Need a Win32 type handle to get file date/time
  183. * using the Win32 APIs, even though the handle we
  184. * will be returning is of the type compatible with
  185. * _open
  186. */
  187. handle = CreateFileA(
  188. pszName,
  189. GENERIC_READ,
  190. FILE_SHARE_READ,
  191. NULL,
  192. OPEN_EXISTING,
  193. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  194. NULL
  195. );
  196. if (handle == INVALID_HANDLE_VALUE)
  197. {
  198. return -1;
  199. }
  200. if (GetFileInformationByHandle(handle, &finfo) == FALSE)
  201. {
  202. CloseHandle(handle);
  203. return -1;
  204. }
  205. cs->start_uncompressed_size = finfo.nFileSizeLow;
  206. FileTimeToLocalFileTime(
  207. &finfo.ftLastWriteTime,
  208. &filetime
  209. );
  210. FileTimeToDosDateTime(
  211. &filetime,
  212. pdate,
  213. ptime
  214. );
  215. attrs = GetFileAttributesA(pszName);
  216. if (attrs == 0xFFFFFFFF)
  217. {
  218. /* failure */
  219. *pattribs = 0;
  220. }
  221. else
  222. {
  223. /*
  224. * Mask out all other bits except these four, since other
  225. * bits are used by the cabinet format to indicate a
  226. * special meaning.
  227. */
  228. *pattribs = (int) (attrs & (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
  229. }
  230. CloseHandle(handle);
  231. /*
  232. * Return handle using _open
  233. */
  234. hf = _open( pszName, _O_RDONLY | _O_BINARY );
  235. if (hf == -1)
  236. return -1; // abort on error
  237. return hf;
  238. }
  239. void set_cab_parameters(PCCAB cab_parms)
  240. {
  241. memset(cab_parms, 0, sizeof(CCAB));
  242. cab_parms->cb = MEDIA_SIZE;
  243. cab_parms->cbFolderThresh = FOLDER_THRESHOLD;
  244. /*
  245. * Don't reserve space for any extensions
  246. */
  247. cab_parms->cbReserveCFHeader = 0;
  248. cab_parms->cbReserveCFFolder = 0;
  249. cab_parms->cbReserveCFData = 0;
  250. /*
  251. * We use this to create the cabinet name
  252. */
  253. cab_parms->iCab = 1;
  254. /*
  255. * If you want to use disk names, use this to
  256. * count disks
  257. */
  258. cab_parms->iDisk = 0;
  259. /*
  260. * Choose your own number
  261. */
  262. cab_parms->setID = 12345;
  263. /*
  264. * Only important if CABs are spanning multiple
  265. * disks, in which case you will want to use a
  266. * real disk name.
  267. *
  268. * Can be left as an empty string.
  269. */
  270. strcpy(cab_parms->szDisk, "");
  271. /* where to store the created CAB files */
  272. strcpy(cab_parms->szCabPath, CabPath);
  273. /* store name of first CAB file */
  274. store_cab_name(cab_parms->szCab, cab_parms->iCab);
  275. }
  276. BOOL Compress (wchar_t *CabName, wchar_t *fileName, DWORD *UploadTime)
  277. {
  278. HFCI hfci;
  279. ERF erf;
  280. CCAB cab_parameters;
  281. int i;
  282. client_state cs;
  283. char FileName [MAX_PATH];
  284. int num_files = 1;
  285. g_CompressedPercentage = 0;
  286. g_CancelCompression = FALSE;
  287. UnicodeToAnsi1(fileName,FileName);
  288. UnicodeToAnsi1(CabName,cCabName);
  289. /*
  290. * Initialise our internal state
  291. */
  292. cs.total_compressed_size = 0;
  293. cs.total_uncompressed_size = 0;
  294. cs.start_uncompressed_size = 0;
  295. set_cab_parameters(&cab_parameters);
  296. hfci = FCICreate(
  297. &erf,
  298. file_placed,
  299. mem_alloc,
  300. mem_free,
  301. fci_open,
  302. fci_read,
  303. fci_write,
  304. fci_close,
  305. fci_seek,
  306. fci_delete,
  307. get_temp_file,
  308. &cab_parameters,
  309. &cs
  310. );
  311. if (hfci == NULL)
  312. {
  313. //printf("FCICreate() failed: code %d [%s]\n",
  314. // erf.erfOper, return_fci_error_string(erf.erfOper)
  315. //);
  316. return FALSE;
  317. }
  318. for (i = 0; i < num_files; i++)
  319. {
  320. char stripped_name[256];
  321. /*
  322. * Don't store the path name in the cabinet file!
  323. */
  324. strip_path(FileName, stripped_name);
  325. if (FALSE == FCIAddFile(
  326. hfci,
  327. FileName, /* file to add */
  328. stripped_name, /* file name in cabinet file */
  329. FALSE, /* file is not executable */
  330. get_next_cabinet,
  331. progress,
  332. get_open_info,
  333. COMPRESSION_TYPE))
  334. {
  335. // printf("FCIAddFile() failed: code %d [%s]\n",
  336. // erf.erfOper, return_fci_error_string(erf.erfOper)
  337. // );
  338. (void) FCIDestroy(hfci);
  339. return FALSE;
  340. }
  341. }
  342. /*
  343. * This will automatically flush the folder first
  344. */
  345. if (FALSE == FCIFlushCabinet(
  346. hfci,
  347. FALSE,
  348. get_next_cabinet,
  349. progress))
  350. {
  351. // printf("FCIFlushCabinet() failed: code %d [%s]\n",
  352. // erf.erfOper, return_fci_error_string(erf.erfOper)
  353. // );
  354. (void) FCIDestroy(hfci);
  355. return FALSE;
  356. }
  357. if (FCIDestroy(hfci) != TRUE)
  358. {
  359. // printf("FCIDestroy() failed: code %d [%s]\n",
  360. // erf.erfOper, return_fci_error_string(erf.erfOper)
  361. // );
  362. return FALSE;
  363. }
  364. //printf(" \r");
  365. // ***************** Add Upload Estimate Here ******************
  366. return TRUE;
  367. }
  368. void strip_path(char *filename, char *stripped_name)
  369. {
  370. char *p;
  371. p = strrchr(filename, '\\');
  372. if (p == NULL)
  373. strcpy(stripped_name, filename);
  374. else
  375. strcpy(stripped_name, p+1);
  376. }
  377. int get_percentage(unsigned long a, unsigned long b)
  378. {
  379. while (a > 10000000)
  380. {
  381. a >>= 3;
  382. b >>= 3;
  383. }
  384. if (b == 0)
  385. return 0;
  386. return ((a*100)/b);
  387. }
  388. char *return_fci_error_string(FCIERROR err)
  389. {
  390. switch (err)
  391. {
  392. case FCIERR_NONE:
  393. return "No error";
  394. case FCIERR_OPEN_SRC:
  395. return "Failure opening file to be stored in cabinet";
  396. case FCIERR_READ_SRC:
  397. return "Failure reading file to be stored in cabinet";
  398. case FCIERR_ALLOC_FAIL:
  399. return "Insufficient memory in FCI";
  400. case FCIERR_TEMP_FILE:
  401. return "Could not create a temporary file";
  402. case FCIERR_BAD_COMPR_TYPE:
  403. return "Unknown compression type";
  404. case FCIERR_CAB_FILE:
  405. return "Could not create cabinet file";
  406. case FCIERR_USER_ABORT:
  407. return "Client requested abort";
  408. case FCIERR_MCI_FAIL:
  409. return "Failure compressing data";
  410. default:
  411. return "Unknown error";
  412. }
  413. }
  414. void UnicodeToAnsi1(wchar_t * pszW, LPSTR ppszA)
  415. {
  416. ULONG cbAnsi, cCharacters;
  417. DWORD dwError;
  418. // If input is null then just return the same.
  419. // return;// NOERROR;
  420. cCharacters = wcslen(pszW)+1;
  421. // Determine number of bytes to be allocated for ANSI string. An
  422. // ANSI string can have at most 2 bytes per character (for Double
  423. // Byte Character Strings.)
  424. cbAnsi = cCharacters*2;
  425. // Use of the OLE allocator is not required because the resultant
  426. // ANSI string will never be passed to another COM component. You
  427. // can use your own allocator.
  428. /// *ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi);
  429. // if (NULL == *ppszA)
  430. // return E_OUTOFMEMORY;
  431. // Convert to ANSI.
  432. if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, ppszA,
  433. cbAnsi, NULL, NULL))
  434. {
  435. dwError = GetLastError();
  436. return;// HRESULT_FROM_WIN32(dwError);
  437. }
  438. //MessageBoxW(NULL,pszW,L"String conversion function recieved",MB_OK);
  439. // MessageBox(NULL,*ppszA,"String Convert Function is returning.",MB_OK);
  440. return;// NOERROR;
  441. }