⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i5comp.c

📁 InstallShield v5.x Compression
💻 C
📖 第 1 页 / 共 4 页
字号:
			((pFile=GetFileDesc(DFT, pCabDesc->cDirs + i))->DescStatus & DESC_INVALID) ||
			!(pFile->DescStatus & DESC_COMPRESSED) ||
			pFile->cbCompressed == 0)
		  )
		  i++;

	if (i >= pCabDesc->cFiles)
		// none found
		return AutoDetectFailed();

	// newer compression lib uses a 2-byte block size value
	// in front of every block of compressed data
	// try to detect that
	NextOfs = pFile->ofsData;
	while (Len < pFile->cbCompressed) {
		DWORD dwRead;
		WORD BlockSize;
		
		SetFilePointer(hCabFile, NextOfs, NULL, FILE_BEGIN);
		if (!ReadFile(hCabFile, &BlockSize, sizeof(BlockSize), &dwRead, NULL) ||
			dwRead != sizeof(BlockSize))
				CantReadFile(GetLastError());

		BlockSize += sizeof(BlockSize);		// had me chasing this for a while =)
		NextOfs += BlockSize;
		Len += BlockSize;
	}

	// if sizes match - it's a new style lib
	optVersion = Len == pFile->cbCompressed ? 51145 : 50149;
	
	return TRUE;
}

void InitZData(RWHANDLES* pHnds)
{
	if (optVersion == 0)
		// version was not specified
		// attemp to autodetect
		AutoDetectZData();

	InitCompressLib();
	pZBuf = Alloc(STD_DECOMP_BUFFER);
	ZDataSetInfo(INFO_BUFFER_PTR, (DWORD)pZBuf);
	ZDataSetInfo(INFO_BUFFER_SIZE, STD_DECOMP_BUFFER);
	ZDataSetInfo(INFO_READ_CALLBACK, (DWORD)ReadData);
	ZDataSetInfo(INFO_WRITE_CALLBACK, (DWORD)WriteData);
	ZDataSetInfo(INFO_CALLBACK_PARAM, (DWORD)pHnds);
}

void ExtractFiles()
{
	LPFILEDESC pFile;
	RWHANDLES rwHnd;
	unsigned int i;
	LPSTR pSlash;
	LPSTR pName;
	LPCABFILELIST pCurrent = pFileList;
	FILETIME filetime;
	DWORD Res;

	if (!IsSingleVolume())
		MultipleNotSupported();

	InitZData(&rwHnd);

	rwHnd.hRead = OpenForRead(pCabPattern);

	while (pCurrent) {
		i = pCurrent->CabIndex;
		pName = pCurrent->FileName;
		pFile = GetFileDesc(DFT, pCabDesc->cDirs + i);

		SetFilePointer(rwHnd.hRead, pFile->ofsData, 0, 0);
		
		pSlash = strrchr(pName, '\\');
		if (pSlash) {
			*pSlash = '\0';
			if (!DirExists(pName))
				CreateDir(pName);
			*pSlash = '\\';
		}

		rwHnd.hWrite = OpenForWrite(pName, CREATE_ALWAYS);
	
		if (pFile->DescStatus & DESC_COMPRESSED) {
			rwHnd.BytesIn = pFile->cbCompressed;
			rwHnd.BytesOut = 0;

			__try {
				if (ZDataStart(0))
					CantDecompress(pName);
				if (Res=ZDataDecompress(0))
					CantDecompress(pName);
				else {
					if (optPrintAll || rwHnd.BytesOut != pFile->cbExpanded)
						fprintf(stdout, "%s", pName);
					if (rwHnd.BytesOut != pFile->cbExpanded)
						NoMatchBytesOut();
					if (optPrintAll || rwHnd.BytesOut != pFile->cbExpanded)
						fprintf(stdout, "\n");
				}
				ZDataEnd();
			} __except(EXCEPTION_EXECUTE_HANDLER) {
				ExceptInDecompress();
			}
		} else {
			TransferData(rwHnd.hRead,
						rwHnd.hWrite,
						pFile->cbExpanded,
						pFile->DescStatus & DESC_ENCRYPTED ? CRYPT_DECRYPT : CRYPT_NONE);
			if (optPrintAll)
				fprintf(stdout, "%s\n", pName);
		}
		DosDateTimeToFileTime((WORD)pFile->FatDate, (WORD)pFile->FatTime, &filetime);
		SetFileTime(rwHnd.hWrite, NULL, NULL, &filetime);
		CloseHandle(rwHnd.hWrite);
		SetFileAttributes(pName, pFile->Attrs);

		pCurrent = pCurrent->pNext;
	}
	CloseHandle(rwHnd.hRead);
}

LPFILEGROUPDESC GetGroupByFile(DWORD index)
{
	LPFILEGROUPDESC pFG;
	DWORD i = 0;

	while (	i < cFileGroups &&
		(index < (pFG=GetFileGroupDesc(pCabDesc, FileGroups, i))->FirstFile ||
		index > pFG->LastFile) )
			i++;
	return i < cFileGroups ? pFG : NULL;
}

void CreateDir(LPSTR dirname)
{
	DWORD dwErr;

	if (!CreateDirectory(dirname, NULL)) {
		dwErr = GetLastError();
		if (dwErr == ERROR_PATH_NOT_FOUND) {
			LPSTR pSlash;
			pSlash = strrchr(dirname, '\\');
			if (pSlash) {
				*pSlash = '\0';
				CreateDir(dirname);
				*pSlash = '\\';
				CreateDir(dirname);
				return;
			}
		}
		if (dwErr == ERROR_ALREADY_EXISTS)
			return;

		fprintf(stderr, "Can not create directory %s\n", dirname);
		CleanExit(9);
	}
}

int CALLBACK ReadData(LPVOID pbuf, LPDWORD size, LPRWHANDLES pHnd)
{
	DWORD dwRead;

	if (!pHnd->BytesIn) {
		*size = 0;
		return 0;
	}
	if (pHnd->BytesIn < *size)
		*size = pHnd->BytesIn;

	if (ReadFile(pHnd->hRead, pbuf, *size, &dwRead, NULL)) {
		pHnd->BytesIn -= dwRead;
		*size = dwRead;
		return 0;
	} else
		return GetLastError();
}

int CALLBACK WriteData(LPVOID pbuf, LPDWORD size, LPRWHANDLES pHnd)
{
	DWORD dwWritten;

	if (WriteFile(pHnd->hWrite, pbuf, *size, &dwWritten, NULL)) {
		*size = dwWritten;
		pHnd->BytesOut += dwWritten;
		return 0;
	} else
		return GetLastError();
}


void ReplaceFiles()
{
	LPFILEDESC pFile;
	LPSTR pName;
	LPFILEGROUPDESC pFG;
	RWHANDLES rwHnd;
	DWORD i;
	LPCABFILELIST pCurrent = pFileList;
	DWORD ofsNew;
	DWORD sizeNew;
	ZCOMPRESSBUF ZParam;
	BOOL Store;

	if (!IsSingleVolume())
		MultipleNotSupported();

	InitZData(&rwHnd);

	rwHnd.hWrite = OpenForWrite(pCabPattern, OPEN_EXISTING);

	while (pCurrent) {
		i = pCurrent->CabIndex;
		pName = pCurrent->FileName;
		pFile = GetFileDesc(DFT, pCabDesc->cDirs + i);

		pFG = GetGroupByFile(i);
	
		rwHnd.hRead = OpenForRead(pName);
		
		{// Clean out the old file from cab
			HANDLE hCabRead;
			DWORD MoveSize;
			DWORD MoveShift;
			DWORD i2;
			DWORD FileSize;
			DWORD Top, Bottom;
			DWORD ofsTop;
			DWORD ofsBottom;
			LPFILEDESC pF;

			hCabRead = OpenForRead(pCabPattern);
			FileSize = ofsTop = GetFileSize(hCabRead, NULL);
			ofsBottom = pFile->ofsData + pFile->cbCompressed;

			// Find file right after the one removing and the last file
			for (i2=0; i2 < pCabDesc->cFiles; i2++) {
				pF = GetFileDesc(DFT, pCabDesc->cDirs + i2);
				if (pF->DescStatus & DESC_INVALID)
					continue;
				if (pF->ofsData > pFile->ofsData && pF->ofsData < ofsTop) {
					Top = i2;
					ofsTop = pF->ofsData;
				}
				if (pF->ofsData > pFile->ofsData && pF->ofsData + pF->cbCompressed > ofsBottom) {
					Bottom = i2;
					ofsBottom = pF->ofsData + pF->cbCompressed;
				}
			}
			MoveSize = FileSize - ofsTop;
			MoveShift = ofsTop - pFile->ofsData;
			
			SetFilePointer(rwHnd.hWrite, pFile->ofsData, NULL, FILE_BEGIN);
			// Shift data up if necessary
			if (MoveSize) {
				SetFilePointer(hCabRead, ofsTop, NULL, FILE_BEGIN);
				TransferData(hCabRead, rwHnd.hWrite, MoveSize, CRYPT_NONE);
			}
			CloseHandle(hCabRead);

			ofsNew = SetFilePointer(rwHnd.hWrite, 0, NULL, FILE_CURRENT);
		
			// Update file descriptors to reflect the change in file position
			for (i2=0; i2 < pCabDesc->cFiles; i2++) {
				pF = GetFileDesc(DFT, pCabDesc->cDirs + i2);
				if (pF->DescStatus & DESC_INVALID)
					continue;
				if (pF->ofsData > pFile->ofsData)
					pF->ofsData -= MoveShift;
			}
		}

		sizeNew = GetFileSize(rwHnd.hRead, NULL);

		if (pFile->DescStatus & DESC_COMPRESSED)
			Store = FALSE;
		else
			Store = TRUE;

		if (!Store) {
			rwHnd.BytesIn = sizeNew;
			rwHnd.BytesOut = 0;

			if (ZDataStart(0))
				CantCompressError(pName);
			if (ZDataCompress(sizeof(ZParam), &ZParam) ||
				sizeNew * 0.95 < rwHnd.BytesOut) {
				CantCompressStore(pName);
				pFile->DescStatus &= ~DESC_COMPRESSED;
				Store = TRUE;
				SetFilePointer(rwHnd.hWrite, ofsNew, NULL, FILE_BEGIN);
				SetFilePointer(rwHnd.hRead, 0, NULL, FILE_BEGIN);
			}
			ZDataEnd();
		}
		if (Store) {
			rwHnd.BytesOut = sizeNew;
			TransferData(rwHnd.hRead,
						rwHnd.hWrite,
						sizeNew,
						pFile->DescStatus & DESC_ENCRYPTED ? CRYPT_ENCRYPT : CRYPT_NONE);
		}
		CloseHandle(rwHnd.hRead);
		if (optPrintAll)
			fprintf(stdout, "%s\n", pName);
		SetEndOfFile(rwHnd.hWrite);

		if (pFG) {
			pFG->cbExpanded += sizeNew - pFile->cbExpanded;
			pFG->cbCompressed += rwHnd.BytesOut - pFile->cbCompressed;
		}
		pFile->cbExpanded = sizeNew;
		pFile->cbCompressed = rwHnd.BytesOut;
		pFile->ofsData = ofsNew;

		pCurrent = pCurrent->pNext;
	}
	CloseHandle(rwHnd.hWrite);
	
	SaveCabHeaders();
}

void AddFiles()
{
	DWORD NextFile;
	DWORD ofsNextDesc;
	DWORD ofsNextName;
	RWHANDLES rwHnd;
	DWORD DataOfs;
	ZCOMPRESSBUF ZParam;
	LPDISKFILELIST pCurrent;
	LPFILEDESC pFile;
	LPFILEGROUPDESC pFG;
	char DName[MAX_PATH];
	DWORD Attrs;
	FILETIME filetime;
	DWORD Res;

	// add new files
	if (!IsSingleVolume())
		MultipleNotSupported();
	if (optFileGroup == -1) {
		fprintf(stderr, "'a': Must specify File Group to add to with -g OR use -f\n");
		CleanExit(25);
	}

	RebuildDFT(&NextFile, &ofsNextDesc, &ofsNextName);

	InitZData(&rwHnd);

	rwHnd.hWrite = OpenForWrite(pCabPattern, OPEN_EXISTING);
	DataOfs = SetFilePointer(rwHnd.hWrite, 0, NULL, FILE_END);
	
	pFG = GetFileGroupDesc(pCabDesc, FileGroups, optFileGroup);
	pCurrent = pDiskList;
	while (pCurrent) {
		strcpy(DName, pCurrent->DiskDir);
		strcat(DName, pCurrent->FileName);
		rwHnd.hRead = OpenForRead(DName);

		DFT[pCabDesc->cDirs + NextFile] = ofsNextDesc;
		ofsNextDesc += sizeof(FILEDESC);
		pFile = GetFileDesc(DFT, pCabDesc->cDirs + NextFile);

		pFile->DescStatus = DESC_COMPRESSED;
		pFile->ofsName = ofsNextName;
		strcpy(GetString(DFT, ofsNextName), pCurrent->FileName);
		ofsNextName += strlen(pCurrent->FileName) + 1;

		pFile->ofsData = DataOfs;
		pFile->DirIndex = pCurrent->CabDirInd;
		rwHnd.BytesIn = GetFileSize(rwHnd.hRead, NULL);
		pFile->cbExpanded = rwHnd.BytesIn;
		rwHnd.BytesOut = 0;

		if (ZDataStart(0))
			CantCompressError(DName);
		if ((Res=ZDataCompress(sizeof(ZParam), &ZParam)) ||
			pFile->cbExpanded * 0.95 < rwHnd.BytesOut) {
			CantCompressStore(DName);
			pFile->DescStatus &= ~DESC_COMPRESSED;
			SetFilePointer(rwHnd.hWrite, DataOfs, NULL, FILE_BEGIN);
			SetFilePointer(rwHnd.hRead, 0, NULL, FILE_BEGIN);
			rwHnd.BytesOut = pFile->cbExpanded;
			TransferData(rwHnd.hRead, rwHnd.hWrite, rwHnd.BytesOut, CRYPT_NONE);
		}
		ZDataEnd();
		if (optPrintAll)
			fprintf(stdout,	"%s\n", DName);
		
		GetFileTime(rwHnd.hRead, NULL, NULL, &filetime);
		CloseHandle(rwHnd.hRead);
		pFile->FatDate = pFile->FatTime = 0;
		FileTimeToDosDateTime(&filetime, (LPWORD)&pFile->FatDate, (LPWORD)&pFile->FatTime);

		pFile->cbCompressed = rwHnd.BytesOut;
		Attrs = GetFileAttributes(DName);
		if (Attrs == -1) {
			Attrs = 0;
			fprintf(stderr, "Could not get file attributes of %s\n", DName);
		}
		pFile->Attrs = Attrs;
		DataOfs = SetFilePointer(rwHnd.hWrite, 0, NULL, FILE_CURRENT);
		
		// update headers
		FirstVolHdr->LastFile = NextFile;
		pCabDesc->cFiles = NextFile + 1;
		pFG->LastFile = NextFile;
		pFG->cbExpanded += pFile->cbExpanded;
		pFG->cbCompressed += pFile->cbCompressed;
		NextFile++;
		
		SaveCabHeaders();

		pCurrent = pCurrent->pNext;
	}
	CloseHandle(rwHnd.hWrite);
}

void RebuildDFT(LPDWORD NextFile, LPDWORD ofsNextDesc, LPDWORD ofsNextName)
{
	LPDIRARRAY pDA;
	LPDISKFILELIST pCurrent;
	DWORD i;
	DWORD NewSize;
	DWORD OldDataOfs, NewDataOfs;
	LPFILEDESC pFile;
	DFTABLE NewDFT;
	DWORD cFilesNew;
	
	// take apart Dirs
	pDA = DirsArrayBuild();
	// insert new dirs in the list
	pCurrent = pDiskList;
	while (pCurrent) {
		pCurrent->CabDirInd = DirsArrayAddDir(&pDA, pCurrent->CabDir);
		pCurrent = pCurrent->pNext;
	}
	// calc new size of the DFT
	cFilesNew = pCabDesc->cFiles + FileCount; 
	NewSize = (cFilesNew + pDA->Count) * sizeof(DWORD); // DF ofs table
	// position of first File Desc.
	*ofsNextDesc = NewSize;
	NewSize += cFilesNew * sizeof(FILEDESC);
	// position of first Name (Dir/File)
	*ofsNextName = NewSize;
	
	for (i=0; i < pCabDesc->cFiles; i++) {
		pFile = GetFileDesc(DFT, pCabDesc->cDirs + i);
		if (pFile->DescStatus & DESC_INVALID)
			continue;
		NewSize += strlen(GetString(DFT, pFile->ofsName)) + 1;
	}
	pCurrent = pDiskList;
	while (pCurrent) {
		NewSize += strlen(pCurrent->FileName) + 1;
		pCurrent = pCurrent->pNext;
	}
	for (i=0; i < pDA->Count; i++)
		NewSize += strlen(pDA->Dirs[i]) + 1;
	// new position of compressed data in cab
	NewDataOfs = CabHdr.ofsCabDesc + pCabDesc->ofsDFT + NewSize;

	// allocate and build new DFT, while moving the optFileGroup to the bottom
	NewDFT = Alloc(NewSize);
	
	// copy dirs
	for (i=0; i < pDA->Count; i++) {
		NewDFT[i] = *ofsNextName;
		strcpy(GetString(NewDFT, *ofsNextName), pDA->Dirs[i]);
		*ofsNextName += strlen(pDA->Dirs[i]) + 1;
	}

	// copy files, update filegroups
	*NextFile = 0;
	for (i=0; i < cFileGroups; i++) {
		if (i == optFileGroup)
			continue;
		CopyFileGroup(DFT, NewDFT, pDA->Count, i, NextFile, ofsNextDesc, ofsNextName);
	}
	CopyFileGroup(DFT, NewDFT, pDA->Count, optFileGroup, NextFile, ofsNextDesc, ofsNextName);

	// update all headers
	Free(DFT);
	DFT = NewDFT;
	pCabDesc->cDirs = pDA->Count;
	Free(pDA);
	pCabDesc->cbDFT = NewSize;
	pCabDesc->cbDFT2 = NewSize;
	
	OldDataOfs = CabHdr.ofsCompData;
	if (NewDataOfs > OldDataOfs) {
		// newer versions have relevant headers separately
		if (ver < ver55) {
			DWORD Shift = NewDataOfs - OldDataOfs;
			// update file descriptors
			for (i=0; i < pCabDesc->cFiles; i++) {
				pFile = GetFileDesc(NewDFT, pCabDesc->cDirs + i);
				pFile->ofsData += Shift;
			}
			// shift Z data down
			ShiftDataDown(pCabPattern, OldDataOfs, Shift);
		}
		// update headers
		CabHdr.ofsCompData = NewDataOfs;
	}
	SaveCabHeaders();
}

void ShiftDataDown(LPSTR FileName, DWORD DataOfs, DWORD Shift)
{
	HANDLE hRead, hWrite;
	DWORD MoveSize;
	DWORD dwTran;
	LPBYTE pBuf;
	DWORD ToTran;

	hRead = OpenForRead(FileName);
	hWrite = OpenForWrite(FileName, OPEN_EXISTING);

	MoveSize = GetFileSize(hRead, NULL) - DataOfs;
	DataOfs += MoveSize;

	if (MoveSize > 262144)
		ToTran = 262144;
	else
		ToTran = MoveSize;

	pBuf = Alloc(ToTran);

	while (MoveSize) {
		if (ToTran > MoveSize)
			ToTran = MoveSize;
		DataOfs -= ToTran;

		SetFilePointer(hRead, DataOfs, NULL, FILE_BEGIN);
		if (!ReadFile(hRead, pBuf, ToTran, &dwTran, NULL) || dwTran != ToTran)
			CantReadFile(GetLastError());
		
		SetFilePointer(hWrite, DataOfs + Shift, NULL, FILE_BEGIN);
		if (!WriteFile(hWrite, pBuf, ToTran, &dwTran, NULL) || dwTran != ToTran)
			CantWriteFile(GetLastError());
		MoveSize -= dwTran;
	}
	Free(pBuf);

	CloseHandle(hRead);
	CloseHandle(hWrite);
}

void CopyFileGroup(DFTABLE OldT, DFTABLE NewT, DWORD cNewDirs, DWORD FGIndex, LPDWORD NextFile, LPDWORD ofsNextDesc, LPDWORD ofsNextName)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -