You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
837 lines
18 KiB
837 lines
18 KiB
//*******************************************************************************************
|
|
//
|
|
// Filename : CabItms.cpp
|
|
//
|
|
// Implementation file for CMemFile, CCabEnum and CCabExtract
|
|
//
|
|
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
|
|
//
|
|
//*******************************************************************************************
|
|
|
|
#include "pch.h"
|
|
#include "ccstock.h"
|
|
#include "thisdll.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "fdi.h"
|
|
#include "cabitms.h"
|
|
|
|
class CMemFile
|
|
{
|
|
public:
|
|
CMemFile(HGLOBAL *phMem, DWORD dwSize);
|
|
~CMemFile() {}
|
|
|
|
BOOL Create(LPCTSTR pszFile);
|
|
BOOL Open(LPCTSTR pszFile, int oflag);
|
|
LONG Seek(LONG dist, int seektype);
|
|
UINT Read(LPVOID pv, UINT cb);
|
|
UINT Write(LPVOID pv, UINT cb);
|
|
HANDLE Close();
|
|
|
|
private:
|
|
HANDLE m_hf;
|
|
|
|
HGLOBAL *m_phMem;
|
|
DWORD m_dwSize;
|
|
LONG m_lLoc;
|
|
} ;
|
|
|
|
|
|
CMemFile::CMemFile(HGLOBAL *phMem, DWORD dwSize) : m_hf(INVALID_HANDLE_VALUE), m_lLoc(0)
|
|
{
|
|
m_phMem = phMem;
|
|
m_dwSize = dwSize;
|
|
|
|
if (phMem)
|
|
{
|
|
*phMem = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CMemFile::Create(LPCTSTR pszFile)
|
|
{
|
|
if (m_phMem)
|
|
{
|
|
if (*m_phMem)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
*m_phMem = GlobalAlloc(LMEM_FIXED, m_dwSize);
|
|
return(*m_phMem != NULL);
|
|
}
|
|
else
|
|
{
|
|
if (m_hf != INVALID_HANDLE_VALUE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
m_hf = CreateFile(pszFile,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
return (m_hf != INVALID_HANDLE_VALUE);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CMemFile::Open(LPCTSTR pszFile, int oflag)
|
|
{
|
|
if (m_phMem)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (m_hf != INVALID_HANDLE_VALUE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
m_hf = CreateFile(pszFile,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
oflag,
|
|
NULL);
|
|
return (m_hf != INVALID_HANDLE_VALUE);
|
|
}
|
|
}
|
|
|
|
|
|
LONG CMemFile::Seek(LONG dist, int seektype)
|
|
{
|
|
if (m_phMem)
|
|
{
|
|
if (!*m_phMem)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
switch (seektype)
|
|
{
|
|
case FILE_BEGIN:
|
|
break;
|
|
|
|
case FILE_CURRENT:
|
|
dist += m_lLoc;
|
|
break;
|
|
|
|
case FILE_END:
|
|
dist = m_dwSize - dist;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
if (dist<0 || dist>(LONG)m_dwSize)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
m_lLoc = dist;
|
|
return(dist);
|
|
}
|
|
else
|
|
{
|
|
return(_llseek((HFILE)HandleToUlong(m_hf), dist, seektype));
|
|
}
|
|
}
|
|
|
|
|
|
UINT CMemFile::Read(LPVOID pv, UINT cb)
|
|
{
|
|
if (m_phMem)
|
|
{
|
|
if (!*m_phMem)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
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((HFILE)HandleToUlong(m_hf), pv, cb));
|
|
}
|
|
}
|
|
|
|
|
|
UINT CMemFile::Write(LPVOID pv, UINT cb)
|
|
{
|
|
if (m_phMem)
|
|
{
|
|
if (!*m_phMem)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
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((HFILE)HandleToUlong(m_hf), (LPCSTR)pv, cb));
|
|
}
|
|
}
|
|
|
|
|
|
HANDLE CMemFile::Close()
|
|
{
|
|
HANDLE hRet;
|
|
|
|
if (m_phMem)
|
|
{
|
|
hRet = *m_phMem ? 0 : INVALID_HANDLE_VALUE;
|
|
}
|
|
else
|
|
{
|
|
hRet = LongToHandle(_lclose((HFILE)HandleToUlong(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_PTR FAR DIAMONDAPI CabOpen(char FAR *pszFile, int oflag, int pmode);
|
|
static UINT FAR DIAMONDAPI CabRead(INT_PTR hf, void FAR *pv, UINT cb);
|
|
static UINT FAR DIAMONDAPI CabWrite(INT_PTR hf, void FAR *pv, UINT cb);
|
|
static int FAR DIAMONDAPI CabClose(INT_PTR hf);
|
|
static long FAR DIAMONDAPI CabSeek(INT_PTR hf, long dist, int seektype);
|
|
|
|
BOOL StartEnum();
|
|
BOOL SimpleEnum(LPCTSTR szCabFile, PFNFDINOTIFY pfnCallBack, LPVOID pv);
|
|
void EndEnum();
|
|
|
|
HFDI m_hfdi;
|
|
ERF m_erf;
|
|
|
|
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_PTR 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=='*' )
|
|
{
|
|
TCHAR szSpillFile[MAX_PATH];
|
|
TCHAR szTempPath[MAX_PATH];
|
|
|
|
if(s_hSpill != NULL)
|
|
return -1;
|
|
|
|
GetTempPath(ARRAYSIZE(szTempPath), szTempPath);
|
|
GetTempFileName(szTempPath, TEXT("fdi"), 0, szSpillFile);
|
|
|
|
s_hSpill = new CMemFile(NULL, 0);
|
|
if (!s_hSpill)
|
|
{
|
|
return(-1);
|
|
}
|
|
if (!s_hSpill->Create(szSpillFile))
|
|
{
|
|
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_PTR)s_hSpill;
|
|
}
|
|
|
|
CMemFile *hFile = new CMemFile(NULL, 0);
|
|
if (!hFile)
|
|
{
|
|
return(-1);
|
|
}
|
|
|
|
TCHAR szFile[MAX_PATH];
|
|
SHAnsiToTChar(pszFile, szFile, ARRAYSIZE(szFile));
|
|
while (!hFile->Open(szFile, oflag))
|
|
{
|
|
// TODO: No UI for inserting a disk at this point
|
|
delete hFile;
|
|
return(-1);
|
|
}
|
|
|
|
return((INT_PTR)hFile);
|
|
}
|
|
|
|
|
|
UINT FAR DIAMONDAPI CCabEnum::CabRead(INT_PTR hf, void FAR *pv, UINT cb)
|
|
{
|
|
CMemFile *hFile = (CMemFile *)hf;
|
|
|
|
return(hFile->Read(pv,cb));
|
|
}
|
|
|
|
|
|
UINT FAR DIAMONDAPI CCabEnum::CabWrite(INT_PTR hf, void FAR *pv, UINT cb)
|
|
{
|
|
CMemFile *hFile = (CMemFile *)hf;
|
|
|
|
return(hFile->Write(pv,cb));
|
|
}
|
|
|
|
|
|
int FAR DIAMONDAPI CCabEnum::CabClose(INT_PTR hf)
|
|
{
|
|
CMemFile *hFile = (CMemFile *)hf;
|
|
|
|
// Special case for the deletion of the spill file.
|
|
if(hFile == s_hSpill)
|
|
{
|
|
s_hSpill = NULL;
|
|
}
|
|
|
|
return (int)HandleToUlong(hFile->Close());
|
|
}
|
|
|
|
|
|
long FAR DIAMONDAPI CCabEnum::CabSeek(INT_PTR 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);
|
|
}
|
|
|
|
m_hfdi = FDICreate(
|
|
CabAlloc,
|
|
CabFree,
|
|
CabOpen,
|
|
CabRead,
|
|
CabWrite,
|
|
CabClose,
|
|
CabSeek,
|
|
cpu80386,
|
|
&m_erf);
|
|
|
|
return(m_hfdi != NULL);
|
|
}
|
|
|
|
|
|
BOOL CCabEnum::SimpleEnum(LPCTSTR szCabFile, PFNFDINOTIFY pfnCallBack, LPVOID pv)
|
|
{
|
|
char szCabPath[MAX_PATH];
|
|
char szCabName[MAX_PATH];
|
|
|
|
// Path should be fully qualified
|
|
char szFile[MAX_PATH];
|
|
SHTCharToAnsi(szCabFile, szFile, ARRAYSIZE(szFile));
|
|
lstrcpynA(szCabPath, szFile, ARRAYSIZE(szCabPath));
|
|
LPSTR pszName = PathFindFileNameA(szCabPath);
|
|
if (!pszName)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
lstrcpynA(szCabName, pszName, ARRAYSIZE(szCabName));
|
|
*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(LPCTSTR szCabFile)
|
|
{
|
|
return(SimpleEnum(szCabFile, CabItemsNotify, this));
|
|
}
|
|
|
|
private:
|
|
static INT_PTR FAR DIAMONDAPI CabItemsNotify(FDINOTIFICATIONTYPE fdint,
|
|
PFDINOTIFICATION pfdin);
|
|
|
|
CCabItems::PFNCABITEM m_pfnCallBack;
|
|
LPARAM m_lParam;
|
|
} ;
|
|
|
|
|
|
INT_PTR FAR DIAMONDAPI CCabItemsCB::CabItemsNotify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
|
{
|
|
CCabItemsCB *pThis = (CCabItemsCB *)pfdin->pv;
|
|
|
|
// uiYield( g_hwndSetup );
|
|
TCHAR szFile[MAX_PATH];
|
|
if (NULL != pfdin->psz1)
|
|
{
|
|
// NOTE: CP_UTF8 is not supported on Win9x!
|
|
SHAnsiToTCharCP((_A_NAME_IS_UTF & pfdin->attribs) ? CP_UTF8 : CP_ACP,
|
|
pfdin->psz1,
|
|
szFile,
|
|
ARRAYSIZE(szFile));
|
|
}
|
|
|
|
switch (fdint)
|
|
{
|
|
case fdintCOPY_FILE:
|
|
pThis->m_pfnCallBack(pfdin->psz1 ? szFile : NULL,
|
|
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(LPCTSTR 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(LPCTSTR szCabFile)
|
|
{
|
|
return(SimpleEnum(szCabFile, CabExtractNotify, this));
|
|
}
|
|
|
|
private:
|
|
static INT_PTR FAR DIAMONDAPI CabExtractNotify(FDINOTIFICATIONTYPE fdint,
|
|
PFDINOTIFICATION pfdin);
|
|
static int CALLBACK CCabExtractCB::BrowseNotify(HWND hwnd, UINT uMsg, LPARAM lParam,
|
|
LPARAM lpData);
|
|
|
|
LPCTSTR 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
|
|
if (lstrlenA(pThis->m_pfdin->psz3) < 3)
|
|
{
|
|
// append if drive root
|
|
PathAddBackslashA(pThis->m_pfdin->psz3);
|
|
}
|
|
SendMessage(hwnd, BFFM_SETSELECTION, 1, (LPARAM)pThis->m_pfdin->psz3);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
INT_PTR 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;
|
|
|
|
TCHAR szFormat[80];
|
|
TCHAR szTitle[80 + 2*MAX_PATH];
|
|
if (pfdin->psz2[0] != '\0')
|
|
{
|
|
LoadString(g_ThisDll.GetInstance(), IDS_NEXTDISKBROWSE, szFormat, ARRAYSIZE(szFormat));
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_ThisDll.GetInstance(), IDS_NEXTCABBROWSE, szFormat, ARRAYSIZE(szFormat));
|
|
}
|
|
wnsprintf(szTitle, ARRAYSIZE(szTitle), szFormat, (LPSTR) (pfdin->psz1), (LPSTR) (pfdin->psz2));
|
|
|
|
BROWSEINFO bi;
|
|
bi.hwndOwner = pThis->m_hwndOwner;
|
|
bi.pidlRoot = NULL;
|
|
bi.pszDisplayName = NULL;
|
|
bi.lpszTitle = szTitle;
|
|
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
|
bi.lpfn = BrowseNotify;
|
|
bi.lParam = (LPARAM)pThis;
|
|
|
|
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
|
|
|
if (bi.pidlRoot)
|
|
{
|
|
ILFree((LPITEMIDLIST)bi.pidlRoot);
|
|
}
|
|
|
|
if (!pidl)
|
|
{
|
|
return(-1);
|
|
}
|
|
|
|
CHAR szPath[MAX_PATH];
|
|
BOOL bSuccess = SHGetPathFromIDListA(pidl, szPath);
|
|
ILFree(pidl);
|
|
|
|
if (bSuccess)
|
|
{
|
|
PathAddBackslashA(szPath);
|
|
StrCpyNA(pfdin->psz3, szPath, 256); // psz3 is 256 bytes long...
|
|
return(1);
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
case fdintCOPY_FILE:
|
|
{
|
|
TCHAR szFile[MAX_PATH];
|
|
if (NULL != pfdin->psz1)
|
|
{
|
|
// NOTE: CP_UTF8 is not supported on Win9x!
|
|
SHAnsiToTCharCP((_A_NAME_IS_UTF & pfdin->attribs) ? CP_UTF8 : CP_ACP,
|
|
pfdin->psz1,
|
|
szFile,
|
|
ARRAYSIZE(szFile));
|
|
}
|
|
else
|
|
{
|
|
szFile[0] = TEXT('\0');
|
|
}
|
|
|
|
HGLOBAL *phMem = pThis->m_pfnCallBack(pfdin->psz1 ? szFile : NULL,
|
|
pfdin->cb,
|
|
pfdin->date,
|
|
pfdin->time,
|
|
pfdin->attribs,
|
|
pThis->m_lParam);
|
|
if (!phMem)
|
|
{
|
|
break;
|
|
}
|
|
|
|
TCHAR 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, PathFindFileName(szFile));
|
|
hFile = new CMemFile(NULL, 0);
|
|
}
|
|
|
|
if (!hFile)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (hFile->Create(szTemp))
|
|
{
|
|
return((INT_PTR)hFile);
|
|
}
|
|
|
|
delete hFile;
|
|
|
|
break;
|
|
}
|
|
|
|
case fdintCLOSE_FILE_INFO:
|
|
{
|
|
CMemFile *hFile = (CMemFile *)pfdin->hf;
|
|
|
|
return(hFile->Close() == 0);
|
|
}
|
|
|
|
default:
|
|
break;
|
|
} // end switch
|
|
|
|
return 0;
|
|
}
|
|
|
|
HRESULT CCabExtract::_DoDragDrop(HWND hwnd, IDataObject* pdo, LPCITEMIDLIST pidlFolder)
|
|
{
|
|
IShellFolder *psf;
|
|
HRESULT hres = SHBindToObject(NULL, IID_IShellFolder, pidlFolder, (LPVOID*)&psf);
|
|
|
|
// This should always succeed because the caller (SHBrowseForFolder) should
|
|
// have weeded out the non-folders.
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
IDropTarget *pdrop;
|
|
|
|
hres = psf->CreateViewObject(NULL, IID_IDropTarget, (void**)&pdrop);
|
|
if (SUCCEEDED(hres)) // Will fail for some targets. (Like Nethood->Entire Network)
|
|
{
|
|
// May fail if items aren't compatible for drag/drop. (Nethood is one example)
|
|
// MK_CONTROL | MKLBUTTON is used to suggest a "copy":
|
|
hres = SHSimulateDrop(pdrop, pdo, MK_CONTROL | MK_LBUTTON, NULL, NULL);
|
|
pdrop->Release();
|
|
}
|
|
|
|
psf->Release();
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
int BrowseCallback(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
switch (msg)
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
{
|
|
// Set the caption. ('Select a destination')
|
|
TCHAR szTitle[100];
|
|
LoadString(g_ThisDll.GetInstance(), IDS_EXTRACTBROWSE_CAPTION, szTitle, ARRAYSIZE(szTitle));
|
|
SetWindowText(hwnd, szTitle);
|
|
|
|
// Set the text of the Ok Button.
|
|
TCHAR szOK[100];
|
|
LoadString(g_ThisDll.GetInstance(), IDS_EXTRACTBROWSE_EXTRACT, szOK, ARRAYSIZE(szOK));
|
|
SendMessage(hwnd, BFFM_SETOKTEXT, 0, (LPARAM)szOK);
|
|
}
|
|
break;
|
|
|
|
case BFFM_SELCHANGED:
|
|
{
|
|
LPITEMIDLIST pidl = (LPITEMIDLIST)lParam;
|
|
BOOL bEnableOk = FALSE;
|
|
IShellFolder *psf;
|
|
LPCITEMIDLIST pidlChild;
|
|
if (SUCCEEDED(SHBindToIDListParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlChild)))
|
|
{
|
|
DWORD dwAttributes = SFGAO_FILESYSTEM;
|
|
psf->GetAttributesOf(1, &pidlChild, &dwAttributes);
|
|
psf->Release();
|
|
bEnableOk = dwAttributes & SFGAO_FILESYSTEM; // is FS?
|
|
}
|
|
|
|
SendMessage(hwnd, BFFM_ENABLEOK, (WPARAM) 0, (LPARAM) bEnableOk);
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL CCabExtract::ExtractToFolder(HWND hwndOwner, IDataObject* pdo, PFNCABEXTRACT pfnCallBack, LPARAM lParam)
|
|
{
|
|
// ASSERT(pdo);
|
|
TCHAR szTitle[120];
|
|
LoadString(g_ThisDll.GetInstance(), IDS_EXTRACTBROWSE, szTitle, ARRAYSIZE(szTitle));
|
|
|
|
BROWSEINFO bi;
|
|
bi.hwndOwner = hwndOwner;
|
|
bi.pidlRoot = NULL;
|
|
bi.pszDisplayName = NULL;
|
|
bi.lpszTitle = szTitle;
|
|
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_UAHINT;
|
|
bi.lpfn = BrowseCallback;
|
|
|
|
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
|
if (!pidl)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
BOOL bSuccess = SUCCEEDED(_DoDragDrop(hwndOwner, pdo, pidl));
|
|
|
|
ILFree(pidl);
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
|
|
BOOL CCabExtract::ExtractItems(HWND hwndOwner, LPCTSTR szDir, PFNCABEXTRACT pfnCallBack, LPARAM lParam)
|
|
{
|
|
// ASSERT(szDir);
|
|
CCabExtractCB cExtract(szDir, hwndOwner, pfnCallBack, lParam);
|
|
|
|
// Display Wait cursor until done copying
|
|
CWaitCursor cWait;
|
|
|
|
return(cExtract.DoEnum(m_szCabFile));
|
|
}
|