windows-nt/Source/XPSP1/NT/admin/pchealth/sr/nttest/srdiag/cab.cpp
2020-09-26 16:20:57 +08:00

702 lines
14 KiB
C++

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <dos.h>
#include <time.h>
#include <tchar.h>
#include <cab.h> //Cab file headers
// #include <main.h> //Main program header file
////////////////////////////
//Cabbing Context Variables
////////////////////////////
ERF erf;
client_state cs;
//Global Definations for some static setting
// Set these to override the defaults
char g_szCabFileLocation[_MAX_PATH] = {""}; //This is the fully qualified path, must have a \ at the end
char g_szCabFileName[_MAX_PATH] = {""}; //this is the file name for the cab.. Suggest that it has a .cab for telling its a cab
extern void Log(char *szString);
extern void Log2(char *szString, char *szString2);
/*
///////////////////////////////
// Cabbing API Helper Functions
/////////////////////./////////
*/
/*
* 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(hf, memory, cb);
if (result != cb)
*err = errno;
return result;
}
FNFCIWRITE(fci_write)
{
unsigned int result;
result = (unsigned int) _write(hf, memory, cb);
if (result != cb)
*err = errno;
return result;
}
FNFCICLOSE(fci_close)
{
int result;
result = _close(hf);
if (result != 0)
*err = errno;
return result;
}
FNFCISEEK(fci_seek)
{
long result;
result = _lseek(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)
{
if (fContinuation)
Log(" (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
}
//** if 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);
}
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);
//printf("Copying folder to cabinet: %d%% \r", percentage);
fflush(stdout);
}
return 0;
}
FNFCIGETNEXTCABINET(get_next_cabinet)
{
char lpBuffer[_MAX_PATH];
/*
* Cabinet counter has been incremented already by FCI
* Store next cabinet name
*/
strGenerateCabFileName(lpBuffer, MAX_COMPUTERNAME_LENGTH +1); //BUGBUG I am just glueing this together, should check for error
strcpy(pccab->szCab, lpBuffer);
/*
* 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;
//*
//* 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, //BUGBUG ARG What should this be???
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING, //OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN
NULL
);
if (INVALID_HANDLE_VALUE == handle)
{
printf("DEBUG: Invalid Handle for CreateFile\n");
printf("DEBUG: %ld\n", GetLastError());
return -1;
}
if (GetFileInformationByHandle(handle, &finfo) == FALSE)
{
printf("DEBUG: GetFileInformation Failed\n");
CloseHandle(handle);
return -1;
}
FileTimeToLocalFileTime(
&finfo.ftLastWriteTime,
&filetime
);
FileTimeToDosDateTime(
&filetime,
pdate,
ptime
);
attrs = GetFileAttributes((const LPCTSTR)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)
{
const char *szCabStorePath="";
char lpBuffer[_MAX_PATH];
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, "MyDisk");
/* where to store the created CAB files */
if( NULL != *g_szCabFileLocation)
{
//make sure that we have a \\ on the end of the path to the cab.
if( '\\' != g_szCabFileLocation[strlen(g_szCabFileLocation)] )
strcat(g_szCabFileLocation, "\\");
strcpy(cab_parms->szCabPath, g_szCabFileLocation);
}
else
{
szCabStorePath = getenv("TEMP");
strcpy(cab_parms->szCabPath, szCabStorePath);
strcat(cab_parms->szCabPath, "\\");
}
//**
//check if last char in path is "\"
// len = strlen(g_szCurrDir);
// if ('\' != g_szCurrDir[len-1])
// strcat(cab_parms->szCabPath, "\\"); //Not the root: Append "\"at end of path
/* store name of first CAB file */
strGenerateCabFileName(lpBuffer, _MAX_PATH); //BUGBUG I am just glueing this together, should check for error
strcpy(cab_parms->szCab, lpBuffer);
sprintf(lpBuffer, "Cab location = %s%s\n", cab_parms->szCabPath, cab_parms->szCab);
Log(lpBuffer);
}
/*
************************************************************************
*
* Function: create_cab()
*
* Initializes the Context to create a CAB File.
* Returns hcfi if successful (context to a Cab file).
*
************************************************************************
*/
HFCI create_cab()
{
// Initialize our internal state
HFCI hfci;
CCAB cab_parameters;
cs.total_compressed_size = 0;
cs.total_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)
{
Log2("FCICreate() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
printf("FCICreate() failed: code %d [%s]\n",
erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
);
return hfci;
}
else
return hfci;
}
/*
********************************************************************************
*
* Function: flush_cab
*
* Forces the Cabinet under construction to be completed and written to disk.
* Returns TRUE if successful
*
********************************************************************************
*/
BOOL flush_cab(HFCI hfci)
{
// This will automatically flush the folder first
if (FALSE == FCIFlushCabinet(
hfci,
FALSE,
get_next_cabinet,
progress))
{
Log2("FCIFlushCabinet() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
printf("FCIFlushCabinet() failed: code %d [%s]\n",
erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
);
(void) FCIDestroy(hfci);
return FALSE;
}
if (FCIDestroy(hfci) != TRUE)
{
Log2("FCIDestroy() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
printf("FCIDestroy() failed: code %d [%s]\n",
erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
);
return FALSE;
}
return TRUE;
}
/*
**************************************************************************************
*
* Function: test_fci
*
* Adds Files to HFCI Context, Cabs them and flushes the folder (generates Cab file).
* Returns TRUE if successfull
*
***************************************************************************************
*/
bool test_fci(HFCI hfci, int num_files, char *file_list[], char *currdir)
{
int i;
// Add files in the Array passed in file_list[]
for (i = 0; (i < num_files)&&(strlen(file_list[i])); i++)
{
char stripped_name[256];
char *szAux;//added ="";
Log("--------------------------------------------------");
Log2("Processing File = ",file_list[i]);
szAux = (char *) malloc(strlen(file_list[i])+strlen(currdir)+1);
if (NULL!= szAux)
{
if (NULL == currdir) // if currdir is empty, then just pass element[i] in argv[]
strcpy(szAux,file_list[i]);
else {
strcpy(szAux,currdir); // else append filename to currdir
strcat(szAux,file_list[i]);
}
if( -1 != (_access(szAux, 0 )) )
{
// Don't store the path name in the cabinet file!
strip_path(szAux, stripped_name);
if (FALSE == FCIAddFile(
hfci, //This was hfci
szAux, /* file to add */
stripped_name, /* file name in cabinet file */
FALSE, /* file is not executable */
get_next_cabinet,
progress,
get_open_info,
COMPRESSION_TYPE))
{
Log2("FCIAddFile() failed: ",return_fci_error_string((FCIERROR)erf.erfOper));
printf("FCIAddFile() failed: code %d [%s]\n",
erf.erfOper, return_fci_error_string((FCIERROR)erf.erfOper)
);
// I need to continue if file can't be added....
// (void) FCIDestroy(hfci);
// return false;
}
else
Log("File Was Added!");
}
else
Log("File does not exist! Continuing... ");
free (szAux);
}
else
Log("Could not allocate enough memory to Cab\n");
} // End for
// Done Adding Files
Log("--------------------------------------------------");
//By here then everything is successful.. If not then you need to uncomment the previous failure return.
return true;
}
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);
}
/*
********************************************************************************
*
* Function: strip_path
*
* Returns the file name of a full path.
*
********************************************************************************
*/
void strip_path(char *filename, char *stripped_name)
{
char *p;
p = strrchr(filename, '\\');
//printf ("Path + Filename= %s\n",filename);
if (p == NULL)
strcpy(stripped_name, filename);
else
strcpy(stripped_name, p+1);
}
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";
}
}
/*
**************************************************************
*
* Function: Generate Cab File name
*
* Output: Global String containing a filename
* szCabFileName = ComputerName + ddmmyy + hhmmss
*
**************************************************************
*/
DWORD strGenerateCabFileName(char *lpBuffer, DWORD dSize)
{
time_t ltime;
struct tm *now;
char tmpbuf[128];
//Check to see if we have an override for the cabname, if so use it.
if( NULL != *g_szCabFileName)
{
strcpy(lpBuffer, g_szCabFileName);
return 0;
}
//
// Copy Computer Name to CabFileName
//
strcpy(lpBuffer, getenv("COMPUTERNAME"));
//GetComputerName((LPTSTR) lpBuffer, &dSize);
//
// Append Undescore character to CabFileName
//
strcat(lpBuffer, "_");
//
// Get System Time and Date
//
time( &ltime );
now = localtime( &ltime );
//
// Convert time/date to mmddyyhhmmss format (24hr)
//
if (strftime( tmpbuf, 128,"%m%d%y_%H%M%S", now))
// Append Timestamp to CabFileName
strcat(lpBuffer, tmpbuf);
else {
Log ("Could not convert system time to mmddyy_hhmmss format\n");
return -1;
}
//Now append on the extension and now we are set.
strcat(lpBuffer, ".cab");
return 0;
}