//*******************************************************************************************
//
// Filename : CabItms.cpp
//
//Implementation file for CMemFile, CCabEnum and CCabExtract
//
// Copyright 1994 - 1998 Microsoft Corporation. All rights reserved
//
//*******************************************************************************************
#include "pch.h"
#include "thisdll.h"
#include "resource.h"
#include "path.h"
#include "fdi.h"
#include "cabitms.h"
class CMemFile
{
public:
CMemFile(HGLOBAL *phMem, DWORD dwSize);
~CMemFile() {}
BOOL Create(LPCSTR pszFile, int fnAttribute);
BOOL Open(LPCSTR pszFile, int oflag);
LONG Seek(LONG dist, int seektype);
UINT Read(LPVOID pv, UINT cb);
UINT Write(LPVOID pv, UINT cb);
HFILE Close();
private:
HFILE m_hf;
HGLOBAL *m_phMem;
DWORD m_dwSize;
LONG m_lLoc;
} ;
CMemFile::CMemFile(HGLOBAL *phMem, DWORD dwSize) : m_hf(HFILE_ERROR), m_lLoc(0)
{
m_phMem = phMem;
m_dwSize = dwSize;
if (phMem)
{
*phMem = NULL;
}
}
BOOL CMemFile::Create(LPCSTR pszFile, int fnAttribute)
{
if (m_phMem)
{
if (*m_phMem)
{
return(FALSE);
}
*m_phMem = GlobalAlloc(LMEM_FIXED, m_dwSize);
return(*m_phMem != NULL);
}
else
{
if (m_hf != HFILE_ERROR)
{
return(FALSE);
}
m_hf = _lcreat(pszFile, fnAttribute);
return(m_hf != HFILE_ERROR);
}
}
BOOL CMemFile::Open(LPCSTR pszFile, int oflag)
{
if (m_phMem)
{
return(FALSE);
}
else
{
if (m_hf != HFILE_ERROR)
{
return(FALSE);
}
m_hf = _lopen(pszFile, oflag);
return(m_hf != HFILE_ERROR);
}
}
LONG CMemFile::Seek(LONG dist, int seektype)
{
if (m_phMem)
{
if (!*m_phMem)
{
return(HFILE_ERROR);
}
switch (seektype)
{
case FILE_BEGIN:
break;
case FILE_CURRENT:
dist += m_lLoc;
break;
case FILE_END:
dist = m_dwSize - dist;
break;
default:
return(HFILE_ERROR);
}
if (dist<0 || dist>(LONG)m_dwSize)
{
return(HFILE_ERROR);
}
m_lLoc = dist;
return(dist);
}
else
{
return(_llseek(m_hf, dist, seektype));
}
}
UINT CMemFile::Read(LPVOID pv, UINT cb)
{
if (m_phMem)
{
if (!*m_phMem)
{
return((UINT)HFILE_ERROR);
}
if (cb > m_dwSize - m_lLoc)
{
cb = m_dwSize - m_lLoc;
}
hmemcpy(pv, (LPSTR)(*m_phMem)+m_lLoc, cb);
m_lLoc += cb;
return(cb);
}
else
{
return(_lread(m_hf, pv, cb));
}
}
UINT CMemFile::Write(LPVOID pv, UINT cb)
{
if (m_phMem)
{
if (!*m_phMem)
{
return((UINT)HFILE_ERROR);
}
if (cb > m_dwSize - m_lLoc)
{
cb = m_dwSize - m_lLoc;
}
hmemcpy((LPSTR)(*m_phMem)+m_lLoc, pv, cb);
m_lLoc += cb;
return(cb);
}
else
{
return(_lwrite(m_hf, (LPCSTR)pv, cb));
}
}
HFILE CMemFile::Close()
{
HFILE hRet;
if (m_phMem)
{
hRet = *m_phMem ? 0 : HFILE_ERROR;
}
else
{
hRet = _lclose(m_hf);
}
delete this;
return(hRet);
}
//*****************************************************************************
//
// CCabEnum
//
// Purpose:
//
// Class encapsulating all the FDI operations
//
// Comments:
//
//*****************************************************************************
class CCabEnum
{
public:
CCabEnum() : m_hfdi(0) {}
~CCabEnum() {}
protected:
static void HUGE * FAR DIAMONDAPI CabAlloc(ULONG cb);
static void FAR DIAMONDAPI CabFree(void HUGE *pv);
static int FAR DIAMONDAPI CabOpen(char FAR *pszFile, int oflag, int pmode);
static UINT FAR DIAMONDAPI CabRead(int hf, void FAR *pv, UINT cb);
static UINT FAR DIAMONDAPI CabWrite(int hf, void FAR *pv, UINT cb);
static int FAR DIAMONDAPI CabClose(int hf);
static long FAR DIAMONDAPI CabSeek(int hf, long dist, int seektype);
BOOL StartEnum();
BOOL SimpleEnum(LPCSTR szCabFile, PFNFDINOTIFY pfnCallBack, LPVOID pv);
void EndEnum();
HFDI m_hfdi;
private:
static CMemFile * s_hSpill;
} ;
CMemFile * CCabEnum::s_hSpill = NULL;
void HUGE * FAR DIAMONDAPI CCabEnum::CabAlloc(ULONG cb)
{
return(GlobalAllocPtr(GHND, cb));
}
void FAR DIAMONDAPI CCabEnum::CabFree(void HUGE *pv)
{
GlobalFreePtr(pv);
}
int FAR DIAMONDAPI CCabEnum::CabOpen(char FAR *pszFile, int oflag, int pmode)
{
if(!pszFile)
{
return -1;
}
// See if we are opening the spill file.
if( *pszFile=='*' )
{
char szSpillFile[MAX_PATH];
char szTempPath[MAX_PATH];
if(s_hSpill != NULL)
return -1;
GetTempPath(sizeof(szTempPath), szTempPath);
GetTempFileName(szTempPath, "fdi", 0, szSpillFile);
s_hSpill = new CMemFile(NULL, 0);
if (!s_hSpill)
{
return(-1);
}
if (!s_hSpill->Create(szSpillFile, 0))
{
delete s_hSpill;
s_hSpill = NULL;
return(-1);
}
// Set its extent.
if( s_hSpill->Seek( ((FDISPILLFILE FAR *)pszFile)->cbFile-1, 0) == HFILE_ERROR)
{
s_hSpill->Close();
s_hSpill = NULL;
return -1;
}
s_hSpill->Write(szSpillFile, 1);
return (int)s_hSpill;
}
CMemFile *hFile = new CMemFile(NULL, 0);
if (!hFile)
{
return(-1);
}
while (!hFile->Open(pszFile, oflag))
{
#if 1// TODO: No UI for inserting a disk at this point
delete hFile;
return(-1);
#else
// Failed to open the source.
if (!LoadString (g_hInst, IDS_DISKPROMPT, szText, MAX_STRTABLE_LEN))
return -1;
char szText[MAX_PATH];
wsprintf (g_pErrorBuffer, (LPSTR)szText, (LPSTR)g_pCabName);
// Use hwndIniting to have a parent window
if ( MyMessageBox(g_hwndIniting, g_pErrorBuffer,
MAKEINTRESOURCE(IDS_DISKPROMPT_TIT),
MB_OKCANCEL|MB_ICONSTOP, 0) == IDOK )
continue;
else
return -1;
#endif
}
return((int)hFile);
}
UINT FAR DIAMONDAPI CCabEnum::CabRead(int hf, void FAR *pv, UINT cb)
{
CMemFile *hFile = (CMemFile *)hf;
if (hFile->Read(pv, cb) != cb)
{
cb = (UINT)-1;
}
return(cb);
}
UINT FAR DIAMONDAPI CCabEnum::CabWrite(int hf, void FAR *pv, UINT cb)
{
CMemFile *hFile = (CMemFile *)hf;
if (hFile->Write(pv, cb) != cb)
{
cb = (UINT)-1;
}
return(cb);
}
int FAR DIAMONDAPI CCabEnum::CabClose(int hf)
{
CMemFile *hFile = (CMemFile *)hf;
// Special case for the deletion of the spill file.
if(hFile == s_hSpill)
{
s_hSpill = NULL;
}
return (hFile->Close());
}
long FAR DIAMONDAPI CCabEnum::CabSeek(int hf, long dist, int seektype)
{
CMemFile *hFile = (CMemFile *)hf;
return(hFile->Seek(dist, seektype));
}
BOOL CCabEnum::StartEnum()
{
if (m_hfdi)
{
// We seem to already be enumerating
return(FALSE);
}
ERF erf;
m_hfdi = FDICreate(
CabAlloc,
CabFree,
CabOpen,
CabRead,
CabWrite,
CabClose,
CabSeek,
cpu80386,
&erf);
return(m_hfdi != NULL);
}
BOOL CCabEnum::SimpleEnum(LPCSTR szCabFile, PFNFDINOTIFY pfnCallBack, LPVOID pv)
{
char szCabPath[MAX_PATH];
char szCabName[MAX_PATH];
// Path should be fully qualified
lstrcpyn(szCabPath, szCabFile, sizeof(szCabPath));
LPSTR pszName = PathFindFileName(szCabPath);
if (!pszName)
{
return(FALSE);
}
lstrcpy(szCabName, pszName);
*pszName = '\0';
if (!StartEnum())
{
return(FALSE);
}
BOOL bRet = FDICopy(
m_hfdi,
szCabName,
szCabPath,// path to cabinet files
0,// flags
pfnCallBack,
NULL,
pv);
EndEnum();
return(bRet);
}
void CCabEnum::EndEnum()
{
if (!m_hfdi)
{
return;
}
FDIDestroy(m_hfdi);
m_hfdi = NULL;
}
class CCabItemsCB : private CCabEnum
{
public:
CCabItemsCB(CCabItems::PFNCABITEM pfnCallBack, LPARAM lParam)
{
m_pfnCallBack = pfnCallBack;
m_lParam = lParam;
}
~CCabItemsCB() {}
BOOL DoEnum(LPCSTR szCabFile)
{
return(SimpleEnum(szCabFile, CabItemsNotify, this));
}
private:
static int FAR DIAMONDAPI CabItemsNotify(FDINOTIFICATIONTYPE fdint,
PFDINOTIFICATION pfdin);
CCabItems::PFNCABITEM m_pfnCallBack;
LPARAM m_lParam;
} ;
int FAR DIAMONDAPI CCabItemsCB::CabItemsNotify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
{
CCabItemsCB *pThis = (CCabItemsCB *)pfdin->pv;
// uiYield( g_hwndSetup );
switch (fdint)
{
case fdintCOPY_FILE:
pThis->m_pfnCallBack(pfdin->psz1, pfdin->cb, pfdin->date, pfdin->time, pfdin->attribs,
pThis->m_lParam);
break;
default:
break;
} // end switch
return 0;
}
//*****************************************************************************
//
// CCabItems::EnumItems
//
// Purpose:
//
// Enumerate the items in the cab file
//
//
// Comments:
//
// lParam contains pointer to CCabFolder
//
//*****************************************************************************
BOOL CCabItems::EnumItems(PFNCABITEM pfnCallBack, LPARAM lParam)
{
CCabItemsCB cItems(pfnCallBack, lParam);
return(cItems.DoEnum(m_szCabFile));
}
//*****************************************************************************
//
// CCabExtractCB
//
// Purpose:
//
// handles the call back while extracting Cab files
//
//
//*****************************************************************************
class CCabExtractCB : private CCabEnum
{
public:
CCabExtractCB(LPCSTR szDir, HWND hwndOwner, CCabExtract::PFNCABEXTRACT pfnCallBack,
LPARAM lParam)
{
m_szDir = szDir;
m_hwndOwner = hwndOwner;
m_pfnCallBack = pfnCallBack;
m_lParam = lParam;
m_bTryNextCab = FALSE;
}
~CCabExtractCB() {}
BOOL DoEnum(LPCSTR szCabFile)
{
return(SimpleEnum(szCabFile, CabExtractNotify, this));
}
private:
static int FAR DIAMONDAPI CabExtractNotify(FDINOTIFICATIONTYPE fdint,
PFDINOTIFICATION pfdin);
static int CALLBACK CCabExtractCB::BrowseNotify(HWND hwnd, UINT uMsg, LPARAM lParam,
LPARAM lpData);
LPCSTR m_szDir;
HWND m_hwndOwner;
CCabExtract::PFNCABEXTRACT m_pfnCallBack;
LPARAM m_lParam;
BOOL m_bTryNextCab;
PFDINOTIFICATION m_pfdin;
} ;
int CALLBACK CCabExtractCB::BrowseNotify(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
CCabExtractCB *pThis = (CCabExtractCB *)lpData;
switch (uMsg)
{
case BFFM_INITIALIZED:
{
// Set initial folder
LPSTR pszEnd = PathAddBackslash(pThis->m_pfdin->psz3);
if (pszEnd - pThis->m_pfdin->psz3 > 3)
{
// No problems if not drive root
*(pszEnd - 1) = '\0';
}
SendMessage(hwnd, BFFM_SETSELECTION, 1, (LPARAM)pThis->m_pfdin->psz3);
break;
}
default:
return(0);
}
return(1);
}
int FAR DIAMONDAPI CCabExtractCB::CabExtractNotify(FDINOTIFICATIONTYPE fdint,
PFDINOTIFICATION pfdin)
{
CCabExtractCB *pThis = (CCabExtractCB *)pfdin->pv;
// uiYield( g_hwndSetup );
switch (fdint)
{
case fdintCABINET_INFO:
pThis->m_bTryNextCab = TRUE;
break;
case fdintNEXT_CABINET:
{
if (pThis->m_bTryNextCab)
{
// Automatically open next cab if already in default dir
pThis->m_bTryNextCab = FALSE;
return(1);
}
pThis->m_pfdin = pfdin;
char szTitle[80];
LoadString(g_ThisDll.GetInstance(), IDS_NEXTCABBROWSE, szTitle, sizeof(szTitle));
BROWSEINFO bi;
bi.hwndOwner = pThis->m_hwndOwner;
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = szTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = BrowseNotify;
bi.lParam = (LPARAM)pThis;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
if (bi.pidlRoot)
{
ILFree((LPITEMIDLIST)bi.pidlRoot);
}
if (!pidl)
{
return(-1);
}
BOOL bSuccess = SHGetPathFromIDList(pidl, pfdin->psz3);
ILFree(pidl);
if (bSuccess)
{
PathAddBackslash(pfdin->psz3);
return(1);
}
return(-1);
}
case fdintCOPY_FILE:
{
HGLOBAL *phMem = pThis->m_pfnCallBack(pfdin->psz1, pfdin->cb, pfdin->date,
pfdin->time, pfdin->attribs, pThis->m_lParam);
if (!phMem)
{
break;
}
char szTemp[MAX_PATH];
CMemFile *hFile;
if (pThis->m_szDir == DIR_MEM)
{
*szTemp = '\0';
hFile = new CMemFile(phMem, pfdin->cb);
}
else
{
PathCombine(szTemp, pThis->m_szDir, pfdin->psz1);
hFile = new CMemFile(NULL, 0);
}
if (!hFile)
{
return(-1);
}
if (hFile->Create(szTemp, OF_WRITE))
{
return((int)hFile);
}
delete hFile;
return(-1);
}
case fdintCLOSE_FILE_INFO:
{
CMemFile *hFile = (CMemFile *)pfdin->hf;
return(hFile->Close() == 0);
}
default:
break;
} // end switch
return 0;
}
BOOL CCabExtract::ExtractItems(HWND hwndOwner, LPCSTR szDir, PFNCABEXTRACT pfnCallBack, LPARAM lParam)
{
char szTempDir[MAX_PATH];
if (!szDir)
{
szDir = szTempDir;
char szTitle[80];
LoadString(g_ThisDll.GetInstance(), IDS_EXTRACTBROWSE, szTitle, sizeof(szTitle));
BROWSEINFO bi;
bi.hwndOwner = hwndOwner;
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = szTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
if (!pidl)
{
return(FALSE);
}
BOOL bSuccess = SHGetPathFromIDList(pidl, szTempDir);
ILFree(pidl);
if (!bSuccess)
{
return(FALSE);
}
}
CCabExtractCB cExtract(szDir, hwndOwner, pfnCallBack, lParam);
// Display Wait cursor until done copying
CWaitCursor cWait;
return(cExtract.DoEnum(m_szCabFile));
}