#include "stdafx.h" #include "Compress.h" char cCabName [MAX_PATH]; char CabPath[256]; ULONG g_CompressedPercentage=0; BOOL g_CancelCompression = FALSE; /* * Memory allocation function */ FNFCIALLOC(mem_alloc) { return malloc(cb); } /* * Memory free function */ FNFCIFREE(mem_free) { free(memory); } /* * File i/o functions */ FNFCIOPEN(fci_open) { int result; result = _open(pszFile, oflag, pmode); if (result == -1) *err = errno; return result; } FNFCIREAD(fci_read) { unsigned int result; result = (unsigned int) _read((int)hf, memory, cb); if (result != cb) *err = errno; return result; } FNFCIWRITE(fci_write) { unsigned int result; result = (unsigned int) _write((int)hf, memory, cb); if (result != cb) *err = errno; return result; } FNFCICLOSE(fci_close) { int result; result = _close((int)hf); if (result != 0) *err = errno; return result; } FNFCISEEK(fci_seek) { long result; result = _lseek((int)hf, dist, seektype); if (result == -1) *err = errno; return result; } FNFCIDELETE(fci_delete) { int result; result = remove(pszFile); if (result != 0) *err = errno; return result; } /* * File placed function called when a file has been committed * to a cabinet */ FNFCIFILEPLACED(file_placed) { /*printf( " placed file '%s' (size %d) on cabinet '%s'\n", pszFile, cbFile, pccab->szCab ); if (fContinuation) printf(" (Above file is a later segment of a continued file)\n"); */ return 0; } /* * Function to obtain temporary files */ FNFCIGETTEMPFILE(get_temp_file) { char *psz; psz = _tempnam("","xx"); // Get a name if ((psz != NULL) && (strlen(psz) < (unsigned)cbTempName)) { strcpy(pszTempName,psz); // Copy to caller's buffer free(psz); // Free temporary name buffer return TRUE; // Success } //** Failed if (psz) { free(psz); } return FALSE; } /* * Progress function */ FNFCISTATUS(progress) { client_state *cs; cs = (client_state *) pv; if (typeStatus == statusFile) { cs->total_compressed_size += cb1; cs->total_uncompressed_size += cb2; /* * Compressing a block into a folder * * cb2 = uncompressed size of block */ /* printf( "Compressing: %9ld -> %9ld \r", cs->total_uncompressed_size, cs->total_compressed_size ); fflush(stdout); */ g_CompressedPercentage = get_percentage(cs->total_uncompressed_size,cs->start_uncompressed_size); } else if (typeStatus == statusFolder) { int percentage; /* * Adding a folder to a cabinet * * cb1 = amount of folder copied to cabinet so far * cb2 = total size of folder */ percentage = get_percentage(cb1, cb2); cs->start_uncompressed_size = cb2; // printf("Copying folder to cabinet: %d%% \r", percentage); fflush(stdout); } if (g_CancelCompression) { // Abort the compression return -1; } return 0; } void store_cab_name(char *cabname, int iCab) { sprintf(cabname, cCabName, iCab); } FNFCIGETNEXTCABINET(get_next_cabinet) { /* * Cabinet counter has been incremented already by FCI */ /* * Store next cabinet name */ store_cab_name(pccab->szCab, pccab->iCab); /* * You could change the disk name here too, if you wanted */ return TRUE; } FNFCIGETOPENINFO(get_open_info) { BY_HANDLE_FILE_INFORMATION finfo; FILETIME filetime; HANDLE handle; DWORD attrs; int hf; client_state *cs; cs = (client_state *) pv; /* * Need a Win32 type handle to get file date/time * using the Win32 APIs, even though the handle we * will be returning is of the type compatible with * _open */ handle = CreateFileA( pszName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if (handle == INVALID_HANDLE_VALUE) { return -1; } if (GetFileInformationByHandle(handle, &finfo) == FALSE) { CloseHandle(handle); return -1; } cs->start_uncompressed_size = finfo.nFileSizeLow; FileTimeToLocalFileTime( &finfo.ftLastWriteTime, &filetime ); FileTimeToDosDateTime( &filetime, pdate, ptime ); attrs = GetFileAttributesA(pszName); if (attrs == 0xFFFFFFFF) { /* failure */ *pattribs = 0; } else { /* * Mask out all other bits except these four, since other * bits are used by the cabinet format to indicate a * special meaning. */ *pattribs = (int) (attrs & (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH)); } CloseHandle(handle); /* * Return handle using _open */ hf = _open( pszName, _O_RDONLY | _O_BINARY ); if (hf == -1) return -1; // abort on error return hf; } void set_cab_parameters(PCCAB cab_parms) { memset(cab_parms, 0, sizeof(CCAB)); cab_parms->cb = MEDIA_SIZE; cab_parms->cbFolderThresh = FOLDER_THRESHOLD; /* * Don't reserve space for any extensions */ cab_parms->cbReserveCFHeader = 0; cab_parms->cbReserveCFFolder = 0; cab_parms->cbReserveCFData = 0; /* * We use this to create the cabinet name */ cab_parms->iCab = 1; /* * If you want to use disk names, use this to * count disks */ cab_parms->iDisk = 0; /* * Choose your own number */ cab_parms->setID = 12345; /* * Only important if CABs are spanning multiple * disks, in which case you will want to use a * real disk name. * * Can be left as an empty string. */ strcpy(cab_parms->szDisk, ""); /* where to store the created CAB files */ strcpy(cab_parms->szCabPath, CabPath); /* store name of first CAB file */ store_cab_name(cab_parms->szCab, cab_parms->iCab); } BOOL Compress (wchar_t *CabName, wchar_t *fileName, DWORD *UploadTime) { HFCI hfci; ERF erf; CCAB cab_parameters; int i; client_state cs; char FileName [MAX_PATH]; int num_files = 1; g_CompressedPercentage = 0; g_CancelCompression = FALSE; UnicodeToAnsi1(fileName,FileName); UnicodeToAnsi1(CabName,cCabName); /* * Initialise our internal state */ cs.total_compressed_size = 0; cs.total_uncompressed_size = 0; cs.start_uncompressed_size = 0; set_cab_parameters(&cab_parameters); hfci = FCICreate( &erf, file_placed, mem_alloc, mem_free, fci_open, fci_read, fci_write, fci_close, fci_seek, fci_delete, get_temp_file, &cab_parameters, &cs ); if (hfci == NULL) { //printf("FCICreate() failed: code %d [%s]\n", // erf.erfOper, return_fci_error_string(erf.erfOper) //); return FALSE; } for (i = 0; i < num_files; i++) { char stripped_name[256]; /* * Don't store the path name in the cabinet file! */ strip_path(FileName, stripped_name); if (FALSE == FCIAddFile( hfci, FileName, /* file to add */ stripped_name, /* file name in cabinet file */ FALSE, /* file is not executable */ get_next_cabinet, progress, get_open_info, COMPRESSION_TYPE)) { // printf("FCIAddFile() failed: code %d [%s]\n", // erf.erfOper, return_fci_error_string(erf.erfOper) // ); (void) FCIDestroy(hfci); return FALSE; } } /* * This will automatically flush the folder first */ if (FALSE == FCIFlushCabinet( hfci, FALSE, get_next_cabinet, progress)) { // printf("FCIFlushCabinet() failed: code %d [%s]\n", // erf.erfOper, return_fci_error_string(erf.erfOper) // ); (void) FCIDestroy(hfci); return FALSE; } if (FCIDestroy(hfci) != TRUE) { // printf("FCIDestroy() failed: code %d [%s]\n", // erf.erfOper, return_fci_error_string(erf.erfOper) // ); return FALSE; } //printf(" \r"); // ***************** Add Upload Estimate Here ****************** return TRUE; } void strip_path(char *filename, char *stripped_name) { char *p; p = strrchr(filename, '\\'); if (p == NULL) strcpy(stripped_name, filename); else strcpy(stripped_name, p+1); } int get_percentage(unsigned long a, unsigned long b) { while (a > 10000000) { a >>= 3; b >>= 3; } if (b == 0) return 0; return ((a*100)/b); } char *return_fci_error_string(FCIERROR err) { switch (err) { case FCIERR_NONE: return "No error"; case FCIERR_OPEN_SRC: return "Failure opening file to be stored in cabinet"; case FCIERR_READ_SRC: return "Failure reading file to be stored in cabinet"; case FCIERR_ALLOC_FAIL: return "Insufficient memory in FCI"; case FCIERR_TEMP_FILE: return "Could not create a temporary file"; case FCIERR_BAD_COMPR_TYPE: return "Unknown compression type"; case FCIERR_CAB_FILE: return "Could not create cabinet file"; case FCIERR_USER_ABORT: return "Client requested abort"; case FCIERR_MCI_FAIL: return "Failure compressing data"; default: return "Unknown error"; } } void UnicodeToAnsi1(wchar_t * pszW, LPSTR ppszA) { ULONG cbAnsi, cCharacters; DWORD dwError; // If input is null then just return the same. // return;// NOERROR; cCharacters = wcslen(pszW)+1; // Determine number of bytes to be allocated for ANSI string. An // ANSI string can have at most 2 bytes per character (for Double // Byte Character Strings.) cbAnsi = cCharacters*2; // Use of the OLE allocator is not required because the resultant // ANSI string will never be passed to another COM component. You // can use your own allocator. /// *ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi); // if (NULL == *ppszA) // return E_OUTOFMEMORY; // Convert to ANSI. if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, ppszA, cbAnsi, NULL, NULL)) { dwError = GetLastError(); return;// HRESULT_FROM_WIN32(dwError); } //MessageBoxW(NULL,pszW,L"String conversion function recieved",MB_OK); // MessageBox(NULL,*ppszA,"String Convert Function is returning.",MB_OK); return;// NOERROR; }