#include "Compress.h"
#include "Utility.h"
#include <io.h>
#include <fcntl.h>
#include <share.h>
namespace
{
FNFCIFILEPLACED(FCIFilePlaced)
{
return 0;
}
FNFCIALLOC(FCIAlloc)
{
return malloc(cb);
}
FNFCIFREE(FCIFree)
{
return free(memory);
}
FNFCIOPEN(FCIOpen)
{
INT_PTR hf = -1;
*err = _sopen_s(&hf, pszFile, oflag | _O_RAW, _SH_DENYWR, pmode);
return hf;
}
FNFCIREAD(FCIRead)
{
return _read(hf, memory, cb);
}
FNFCIWRITE(FCIWrite)
{
return _write(hf, memory, cb);
}
FNFCICLOSE(FCIClose)
{
return _close(hf);
}
FNFCISEEK(FCISeek)
{
return _lseek(hf, dist, seektype);
}
FNFCIDELETE(FCIDelete)
{
return remove(pszFile);
}
FNFCIGETTEMPFILE(FCIGetTempFile)
{
CHAR szTempPath[MAX_PATH];
CHAR szTempFile[MAX_PATH];
if(GetTempPathA(MAX_PATH, szTempPath) == 0)
{
return FALSE;
}
if(GetTempFileNameA(szTempPath, "CABINET", 0, szTempFile) == 0)
{
return FALSE;
}
if(!DeleteFileA(szTempFile))
{
return FALSE;
}
HRESULT hr = StringCbCopyA(pszTempName, cbTempName, szTempFile);
return SUCCEEDED(hr);
}
FNFCIGETNEXTCABINET(FCIGetNextCabinet)
{
HRESULT hr = StringCbPrintfA(pccab->szCab, CB_MAX_CABINET_NAME, reinterpret_cast<PCSTR>(pv), pccab->iCab);
return SUCCEEDED(hr);
}
FNFCISTATUS(FCIStatus)
{
return 0;
}
FNFCIGETOPENINFO(FCIGetOpenInfo)
{
WIN32_FIND_DATAA FindFileData;
HANDLE hFind = FindFirstFileA(pszName, &FindFileData);
if(hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
Cabinet::Utility::FileTimeToDosTime(FindFileData.ftLastWriteTime, pdate, ptime);
*pattribs = static_cast<USHORT>(FindFileData.dwFileAttributes);
}
return FCIOpen(pszName, _O_RDONLY, 0, err, pv);
}
} //anonymous namespace
Cabinet::CCompress::CCompress() : m_hFCI(NULL)
{
m_szCab[0] = '\0';
}
Cabinet::CCompress::~CCompress()
{
_Destroy();
}
BOOL Cabinet::CCompress::Create(ULONG cbCab, LPCSTR lpCabPath)
{
_Destroy();
ERF erf;
CCAB ccab = {};
ccab.cb = cbCab;
PCCH pBackslash = strrchr(lpCabPath, '\\');
if(pBackslash == NULL)
{
return FALSE;
}
if(cbCab == 0)
{
StringCbCopyA(ccab.szCab, CB_MAX_CABINET_NAME, pBackslash + 1);
}
else
{
PCCH pExtension = strrchr(pBackslash + 1, '.');
if(pExtension == NULL)
{
StringCbCopyA(m_szCab, CB_MAX_CABINET_NAME, pBackslash + 1);
StringCbCatA(m_szCab, CB_MAX_CABINET_NAME, "%02d");
}
else
{
StringCbCopyNA(m_szCab, CB_MAX_CABINET_NAME, pBackslash + 1, pExtension - pBackslash - 1);
StringCbCatA(m_szCab, CB_MAX_CABINET_NAME, "%02d");
StringCbCatA(m_szCab, CB_MAX_CABINET_NAME, pExtension);
}
FCIGetNextCabinet(&ccab, 0, m_szCab);
}
StringCbCopyNA(ccab.szCabPath, CB_MAX_CAB_PATH, lpCabPath, pBackslash - lpCabPath + 1);
m_hFCI = FCICreate(&erf, FCIFilePlaced, FCIAlloc, FCIFree, FCIOpen, FCIRead, FCIWrite, FCIClose, FCISeek, FCIDelete, FCIGetTempFile, &ccab, m_szCab);
return m_hFCI != NULL;
}
BOOL Cabinet::CCompress::AddFile(LPCSTR lpSourceFile) CONST
{
PCCH pBackslash = strrchr(lpSourceFile, '\\');
if(pBackslash == NULL)
{
return FALSE;
}
CHAR szSourceFile[CB_MAX_CAB_PATH];
StringCbCopyA(szSourceFile, CB_MAX_CAB_PATH, lpSourceFile);
CHAR szFileName[CB_MAX_CABINET_NAME];
StringCbCopyA(szFileName, CB_MAX_CABINET_NAME, pBackslash + 1);
return FCIAddFile(m_hFCI, szSourceFile, szFileName, FALSE, FCIGetNextCabinet, FCIStatus, FCIGetOpenInfo, tcompTYPE_MSZIP);
}
BOOL Cabinet::CCompress::AddFolder(LPCSTR lpSourceFolder) CONST
{
CHAR szSourceFolder[MAX_PATH];
StringCbCopyA(szSourceFolder, MAX_PATH, lpSourceFolder);
Utility::PathRemoveBackslash(szSourceFolder);
PCCH pBackslash = strrchr(szSourceFolder, '\\');
if(pBackslash == NULL)
{
return FALSE;
}
return _AddFolder(szSourceFolder, pBackslash - szSourceFolder + 1);
}
BOOL Cabinet::CCompress::FlushCabinet() CONST
{
return FCIFlushCabinet(m_hFCI, FALSE, FCIGetNextCabinet, FCIStatus);
}
BOOL Cabinet::CCompress::_AddFolder(LPCSTR lpSourceFolder, SIZE_T Offset) CONST
{
CHAR szFindFile[MAX_PATH];
StringCbCopyA(szFindFile, MAX_PATH, lpSourceFolder);
StringCbCatA(szFindFile, MAX_PATH, "\\*.*");
SIZE_T cb = strlen(lpSourceFolder) + 1;
BOOL bRet = FALSE;
WIN32_FIND_DATAA FindFileData;
HANDLE hFind = FindFirstFileA(szFindFile, &FindFileData);
if(hFind != INVALID_HANDLE_VALUE)
{
do
{
if(strcmp(FindFileData.cFileName, ".") == 0 || strcmp(FindFileData.cFileName, "..") == 0)
{
continue;
}
StringCbCopyA(szFindFile + cb, MAX_PATH, FindFileData.cFileName);
if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
{
bRet = _AddFolder(szFindFile, Offset);
if(!bRet)
{
break;
}
}
else
{
bRet = FCIAddFile(m_hFCI, szFindFile, szFindFile + Offset, FALSE, FCIGetNextCabinet, FCIStatus, FCIGetOpenInfo, tcompTYPE_MSZIP);
if(!bRet)
{
break;
}
}
}
while(FindNextFileA(hFind, &FindFileData));
FindClose(hFind);
}
return bRet;
}
VOID Cabinet::CCompress::_Destroy()
{
if(m_hFCI != NULL)
{
FCIDestroy(m_hFCI);
m_hFCI = NULL;
}
}