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.

701 lines
14 KiB

  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <io.h>
  5. #include <dos.h>
  6. #include <time.h>
  7. #include <tchar.h>
  8. #include <cab.h> //Cab file headers
  9. // #include <main.h> //Main program header file
  10. ////////////////////////////
  11. //Cabbing Context Variables
  12. ////////////////////////////
  13. ERF erf;
  14. client_state cs;
  15. //Global Definations for some static setting
  16. // Set these to override the defaults
  17. char g_szCabFileLocation[_MAX_PATH] = {""}; //This is the fully qualified path, must have a \ at the end
  18. char g_szCabFileName[_MAX_PATH] = {""}; //this is the file name for the cab.. Suggest that it has a .cab for telling its a cab
  19. extern void Log(char *szString);
  20. extern void Log2(char *szString, char *szString2);
  21. /*
  22. ///////////////////////////////
  23. // Cabbing API Helper Functions
  24. /////////////////////./////////
  25. */
  26. /*
  27. * Memory allocation function
  28. */
  29. FNFCIALLOC(mem_alloc)
  30. {
  31. return malloc(cb);
  32. }
  33. /*
  34. * Memory free function
  35. */
  36. FNFCIFREE(mem_free)
  37. {
  38. free(memory);
  39. }
  40. /*
  41. * File i/o functions
  42. */
  43. FNFCIOPEN(fci_open)
  44. {
  45. int result;
  46. result = _open(pszFile, oflag, pmode);
  47. if (result == -1)
  48. *err = errno;
  49. return result;
  50. }
  51. FNFCIREAD(fci_read)
  52. {
  53. unsigned int result;
  54. result = (unsigned int) _read(hf, memory, cb);
  55. if (result != cb)
  56. *err = errno;
  57. return result;
  58. }
  59. FNFCIWRITE(fci_write)
  60. {
  61. unsigned int result;
  62. result = (unsigned int) _write(hf, memory, cb);
  63. if (result != cb)
  64. *err = errno;
  65. return result;
  66. }
  67. FNFCICLOSE(fci_close)
  68. {
  69. int result;
  70. result = _close(hf);
  71. if (result != 0)
  72. *err = errno;
  73. return result;
  74. }
  75. FNFCISEEK(fci_seek)
  76. {
  77. long result;
  78. result = _lseek(hf, dist, seektype);
  79. if (result == -1)
  80. *err = errno;
  81. return result;
  82. }
  83. FNFCIDELETE(fci_delete)
  84. {
  85. int result;
  86. result = remove(pszFile);
  87. if (result != 0)
  88. *err = errno;
  89. return result;
  90. }
  91. /*
  92. * File placed function called when a file has been committed to a cabinet
  93. */
  94. FNFCIFILEPLACED(file_placed)
  95. {
  96. if (fContinuation)
  97. Log(" (Above file is a later segment of a continued file)\n");
  98. return 0;
  99. }
  100. /*
  101. * Function to obtain temporary files
  102. */
  103. FNFCIGETTEMPFILE(get_temp_file)
  104. {
  105. char *psz;
  106. psz = _tempnam("","xx"); // Get a name
  107. if ((psz != NULL) && (strlen(psz) < (unsigned)cbTempName)) {
  108. strcpy(pszTempName,psz); // Copy to caller's buffer
  109. free(psz); // Free temporary name buffer
  110. return TRUE; // Success
  111. }
  112. //** if Failed
  113. if (psz) {
  114. free(psz);
  115. }
  116. return FALSE;
  117. }
  118. /*
  119. * Progress function
  120. */
  121. FNFCISTATUS(progress)
  122. {
  123. client_state *cs;
  124. cs = (client_state *) pv;
  125. if (typeStatus == statusFile)
  126. {
  127. cs->total_compressed_size += cb1;
  128. cs->total_uncompressed_size += cb2;
  129. /*
  130. * Compressing a block into a folder
  131. * cb2 = uncompressed size of block
  132. */
  133. //printf(
  134. // "Compressing: %9ld -> %9ld \r",
  135. // cs->total_uncompressed_size,
  136. // cs->total_compressed_size
  137. //);
  138. fflush(stdout);
  139. }
  140. else if (typeStatus == statusFolder)
  141. {
  142. int percentage;
  143. /*
  144. * Adding a folder to a cabinet
  145. * cb1 = amount of folder copied to cabinet so far
  146. * cb2 = total size of folder
  147. */
  148. percentage = get_percentage(cb1, cb2);
  149. //printf("Copying folder to cabinet: %d%% \r", percentage);
  150. fflush(stdout);
  151. }
  152. return 0;
  153. }
  154. FNFCIGETNEXTCABINET(get_next_cabinet)
  155. {
  156. char lpBuffer[_MAX_PATH];
  157. /*
  158. * Cabinet counter has been incremented already by FCI
  159. * Store next cabinet name
  160. */
  161. strGenerateCabFileName(lpBuffer, MAX_COMPUTERNAME_LENGTH +1); //BUGBUG I am just glueing this together, should check for error
  162. strcpy(pccab->szCab, lpBuffer);
  163. /*
  164. * You could change the disk name here too, if you wanted
  165. */
  166. return TRUE;
  167. }
  168. FNFCIGETOPENINFO(get_open_info)
  169. {
  170. BY_HANDLE_FILE_INFORMATION finfo;
  171. FILETIME filetime;
  172. HANDLE handle;
  173. DWORD attrs;
  174. int hf;
  175. //*
  176. //* Need a Win32 type handle to get file date/time
  177. //* using the Win32 APIs, even though the handle we
  178. //* will be returning is of the type compatible with
  179. //* _open
  180. //*
  181. handle = CreateFileA(
  182. pszName, //BUGBUG ARG What should this be???
  183. GENERIC_READ,
  184. FILE_SHARE_READ,
  185. NULL,
  186. OPEN_EXISTING, //OPEN_EXISTING
  187. FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN
  188. NULL
  189. );
  190. if (INVALID_HANDLE_VALUE == handle)
  191. {
  192. printf("DEBUG: Invalid Handle for CreateFile\n");
  193. printf("DEBUG: %ld\n", GetLastError());
  194. return -1;
  195. }
  196. if (GetFileInformationByHandle(handle, &finfo) == FALSE)
  197. {
  198. printf("DEBUG: GetFileInformation Failed\n");
  199. CloseHandle(handle);
  200. return -1;
  201. }
  202. FileTimeToLocalFileTime(
  203. &finfo.ftLastWriteTime,
  204. &filetime
  205. );
  206. FileTimeToDosDateTime(
  207. &filetime,
  208. pdate,
  209. ptime
  210. );
  211. attrs = GetFileAttributes((const LPCTSTR)pszName);
  212. if (attrs == 0xFFFFFFFF)
  213. {
  214. // failure
  215. *pattribs = 0;
  216. }
  217. else
  218. {
  219. //*
  220. //* Mask out all other bits except these four, since other
  221. //* bits are used by the cabinet format to indicate a
  222. //* special meaning.
  223. //*
  224. *pattribs = (int) (attrs & (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
  225. }
  226. CloseHandle(handle);
  227. //*
  228. //* Return handle using _open
  229. //*
  230. hf = _open( pszName, _O_RDONLY | _O_BINARY );
  231. if (hf == -1)
  232. return -1; // abort on error
  233. return hf;
  234. }
  235. void set_cab_parameters(PCCAB cab_parms)
  236. {
  237. const char *szCabStorePath="";
  238. char lpBuffer[_MAX_PATH];
  239. memset(cab_parms, 0, sizeof(CCAB));
  240. cab_parms->cb = MEDIA_SIZE;
  241. cab_parms->cbFolderThresh = FOLDER_THRESHOLD;
  242. /*
  243. * Don't reserve space for any extensions
  244. */
  245. cab_parms->cbReserveCFHeader = 0;
  246. cab_parms->cbReserveCFFolder = 0;
  247. cab_parms->cbReserveCFData = 0;
  248. /*
  249. * We use this to create the cabinet name
  250. */
  251. cab_parms->iCab = 1;
  252. /*
  253. * If you want to use disk names, use this to
  254. * count disks
  255. */
  256. cab_parms->iDisk = 0;
  257. /*
  258. * Choose your own number
  259. */
  260. cab_parms->setID = 12345;
  261. /*
  262. * Only important if CABs are spanning multiple
  263. * disks, in which case you will want to use a
  264. * real disk name.
  265. *
  266. * Can be left as an empty string.
  267. */
  268. strcpy(cab_parms->szDisk, "MyDisk");
  269. /* where to store the created CAB files */
  270. if( NULL != *g_szCabFileLocation)
  271. {
  272. //make sure that we have a \\ on the end of the path to the cab.
  273. if( '\\' != g_szCabFileLocation[strlen(g_szCabFileLocation)] )
  274. strcat(g_szCabFileLocation, "\\");
  275. strcpy(cab_parms->szCabPath, g_szCabFileLocation);
  276. }
  277. else
  278. {
  279. szCabStorePath = getenv("TEMP");
  280. strcpy(cab_parms->szCabPath, szCabStorePath);
  281. strcat(cab_parms->szCabPath, "\\");
  282. }
  283. //**
  284. //check if last char in path is "\"
  285. // len = strlen(g_szCurrDir);
  286. // if ('\' != g_szCurrDir[len-1])
  287. // strcat(cab_parms->szCabPath, "\\"); //Not the root: Append "\"at end of path
  288. /* store name of first CAB file */
  289. strGenerateCabFileName(lpBuffer, _MAX_PATH); //BUGBUG I am just glueing this together, should check for error
  290. strcpy(cab_parms->szCab, lpBuffer);
  291. sprintf(lpBuffer, "Cab location = %s%s\n", cab_parms->szCabPath, cab_parms->szCab);
  292. Log(lpBuffer);
  293. }
  294. /*
  295. ************************************************************************
  296. *
  297. * Function: create_cab()
  298. *
  299. * Initializes the Context to create a CAB File.
  300. * Returns hcfi if successful (context to a Cab file).
  301. *
  302. ************************************************************************
  303. */
  304. HFCI create_cab()
  305. {
  306. // Initialize our internal state
  307. HFCI hfci;
  308. CCAB cab_parameters;
  309. cs.total_compressed_size = 0;
  310. cs.total_uncompressed_size = 0;
  311. set_cab_parameters(&cab_parameters);
  312. hfci = FCICreate(
  313. &erf,
  314. file_placed,
  315. mem_alloc,
  316. mem_free,
  317. fci_open,
  318. fci_read,
  319. fci_write,
  320. fci_close,
  321. fci_seek,
  322. fci_delete,
  323. get_temp_file,
  324. &cab_parameters,
  325. &cs
  326. );
  327. if (hfci == NULL)
  328. {
  329. Log2("FCICreate() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
  330. printf("FCICreate() failed: code %d [%s]\n",
  331. erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
  332. );
  333. return hfci;
  334. }
  335. else
  336. return hfci;
  337. }
  338. /*
  339. ********************************************************************************
  340. *
  341. * Function: flush_cab
  342. *
  343. * Forces the Cabinet under construction to be completed and written to disk.
  344. * Returns TRUE if successful
  345. *
  346. ********************************************************************************
  347. */
  348. BOOL flush_cab(HFCI hfci)
  349. {
  350. // This will automatically flush the folder first
  351. if (FALSE == FCIFlushCabinet(
  352. hfci,
  353. FALSE,
  354. get_next_cabinet,
  355. progress))
  356. {
  357. Log2("FCIFlushCabinet() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
  358. printf("FCIFlushCabinet() failed: code %d [%s]\n",
  359. erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
  360. );
  361. (void) FCIDestroy(hfci);
  362. return FALSE;
  363. }
  364. if (FCIDestroy(hfci) != TRUE)
  365. {
  366. Log2("FCIDestroy() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
  367. printf("FCIDestroy() failed: code %d [%s]\n",
  368. erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
  369. );
  370. return FALSE;
  371. }
  372. return TRUE;
  373. }
  374. /*
  375. **************************************************************************************
  376. *
  377. * Function: test_fci
  378. *
  379. * Adds Files to HFCI Context, Cabs them and flushes the folder (generates Cab file).
  380. * Returns TRUE if successfull
  381. *
  382. ***************************************************************************************
  383. */
  384. bool test_fci(HFCI hfci, int num_files, char *file_list[], char *currdir)
  385. {
  386. int i;
  387. // Add files in the Array passed in file_list[]
  388. for (i = 0; (i < num_files)&&(strlen(file_list[i])); i++)
  389. {
  390. char stripped_name[256];
  391. char *szAux;//added ="";
  392. Log("--------------------------------------------------");
  393. Log2("Processing File = ",file_list[i]);
  394. szAux = (char *) malloc(strlen(file_list[i])+strlen(currdir)+1);
  395. if (NULL!= szAux)
  396. {
  397. if (NULL == currdir) // if currdir is empty, then just pass element[i] in argv[]
  398. strcpy(szAux,file_list[i]);
  399. else {
  400. strcpy(szAux,currdir); // else append filename to currdir
  401. strcat(szAux,file_list[i]);
  402. }
  403. if( -1 != (_access(szAux, 0 )) )
  404. {
  405. // Don't store the path name in the cabinet file!
  406. strip_path(szAux, stripped_name);
  407. if (FALSE == FCIAddFile(
  408. hfci, //This was hfci
  409. szAux, /* file to add */
  410. stripped_name, /* file name in cabinet file */
  411. FALSE, /* file is not executable */
  412. get_next_cabinet,
  413. progress,
  414. get_open_info,
  415. COMPRESSION_TYPE))
  416. {
  417. Log2("FCIAddFile() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
  418. printf("FCIAddFile() failed: code %d [%s]\n",
  419. erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
  420. );
  421. // I need to continue if file can't be added....
  422. // (void) FCIDestroy(hfci);
  423. // return false;
  424. }
  425. else
  426. Log("File Was Added!");
  427. }
  428. else
  429. Log("File does not exist! Continuing... ");
  430. free (szAux);
  431. }
  432. else
  433. Log("Could not allocate enough memory to Cab\n");
  434. } // End for
  435. // Done Adding Files
  436. Log("--------------------------------------------------");
  437. //By here then everything is successful.. If not then you need to uncomment the previous failure return.
  438. return true;
  439. }
  440. int get_percentage(unsigned long a, unsigned long b)
  441. {
  442. while (a > 10000000)
  443. {
  444. a >>= 3;
  445. b >>= 3;
  446. }
  447. if (b == 0)
  448. return 0;
  449. return ((a*100)/b);
  450. }
  451. /*
  452. ********************************************************************************
  453. *
  454. * Function: strip_path
  455. *
  456. * Returns the file name of a full path.
  457. *
  458. ********************************************************************************
  459. */
  460. void strip_path(char *filename, char *stripped_name)
  461. {
  462. char *p;
  463. p = strrchr(filename, '\\');
  464. //printf ("Path + Filename= %s\n",filename);
  465. if (p == NULL)
  466. strcpy(stripped_name, filename);
  467. else
  468. strcpy(stripped_name, p+1);
  469. }
  470. char *return_fci_error_string(FCIERROR err)
  471. {
  472. switch (err)
  473. {
  474. case FCIERR_NONE:
  475. return "No error";
  476. case FCIERR_OPEN_SRC:
  477. return "Failure opening file to be stored in cabinet";
  478. case FCIERR_READ_SRC:
  479. return "Failure reading file to be stored in cabinet";
  480. case FCIERR_ALLOC_FAIL:
  481. return "Insufficient memory in FCI";
  482. case FCIERR_TEMP_FILE:
  483. return "Could not create a temporary file";
  484. case FCIERR_BAD_COMPR_TYPE:
  485. return "Unknown compression type";
  486. case FCIERR_CAB_FILE:
  487. return "Could not create cabinet file";
  488. case FCIERR_USER_ABORT:
  489. return "Client requested abort";
  490. case FCIERR_MCI_FAIL:
  491. return "Failure compressing data";
  492. default:
  493. return "Unknown error";
  494. }
  495. }
  496. /*
  497. **************************************************************
  498. *
  499. * Function: Generate Cab File name
  500. *
  501. * Output: Global String containing a filename
  502. * szCabFileName = ComputerName + ddmmyy + hhmmss
  503. *
  504. **************************************************************
  505. */
  506. DWORD strGenerateCabFileName(char *lpBuffer, DWORD dSize)
  507. {
  508. time_t ltime;
  509. struct tm *now;
  510. char tmpbuf[128];
  511. //Check to see if we have an override for the cabname, if so use it.
  512. if( NULL != *g_szCabFileName)
  513. {
  514. strcpy(lpBuffer, g_szCabFileName);
  515. return 0;
  516. }
  517. //
  518. // Copy Computer Name to CabFileName
  519. //
  520. strcpy(lpBuffer, getenv("COMPUTERNAME"));
  521. //GetComputerName((LPTSTR) lpBuffer, &dSize);
  522. //
  523. // Append Undescore character to CabFileName
  524. //
  525. strcat(lpBuffer, "_");
  526. //
  527. // Get System Time and Date
  528. //
  529. time( &ltime );
  530. now = localtime( &ltime );
  531. //
  532. // Convert time/date to mmddyyhhmmss format (24hr)
  533. //
  534. if (strftime( tmpbuf, 128,"%m%d%y_%H%M%S", now))
  535. // Append Timestamp to CabFileName
  536. strcat(lpBuffer, tmpbuf);
  537. else {
  538. Log ("Could not convert system time to mmddyy_hhmmss format\n");
  539. return -1;
  540. }
  541. //Now append on the extension and now we are set.
  542. strcat(lpBuffer, ".cab");
  543. return 0;
  544. }