433 lines
11 KiB
C++
433 lines
11 KiB
C++
|
#include "enum.h"
|
||
|
|
||
|
BOOL GetVersion(LPCONTROLPIDL pcpidl, LPTSTR lpszBuf);
|
||
|
BOOL GetTimeInfo(
|
||
|
BOOL bCreation, LPCONTROLPIDL pcpidl,
|
||
|
FILETIME* lpTime, LPTSTR lpszBuf, BOOL bShowTime);
|
||
|
|
||
|
// Also defined in nt\private\inet\urlmon\isctrl.cxx
|
||
|
const TCHAR *g_pszLastCheckDateKey = "LastCheckDate";
|
||
|
const TCHAR *g_pszUpdateInfo = "UpdateInfo";
|
||
|
|
||
|
#if defined(ALIGNMENT_MACHINE)
|
||
|
BOOL
|
||
|
__inline
|
||
|
static
|
||
|
uaGetControlInfo(
|
||
|
IN HANDLE hControlHandle,
|
||
|
IN UINT nFlag,
|
||
|
IN OUT DWORD UNALIGNED *lpdwuData,
|
||
|
IN OUT LPTSTR lpszBuf,
|
||
|
IN int nBufLen
|
||
|
)
|
||
|
{
|
||
|
DWORD dwData;
|
||
|
LPDWORD lpdwData;
|
||
|
BOOL result;
|
||
|
|
||
|
if (lpdwuData != NULL) {
|
||
|
dwData = *lpdwuData;
|
||
|
lpdwData = &dwData;
|
||
|
} else {
|
||
|
lpdwData = NULL;
|
||
|
}
|
||
|
|
||
|
result = GetControlInfo( hControlHandle,
|
||
|
nFlag,
|
||
|
lpdwData,
|
||
|
lpszBuf,
|
||
|
nBufLen );
|
||
|
|
||
|
if (lpdwuData != NULL) {
|
||
|
*lpdwuData = dwData;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
__inline
|
||
|
static
|
||
|
uaGetTimeInfo(
|
||
|
IN BOOL bCreation,
|
||
|
IN OUT LPCONTROLPIDL pcpidl,
|
||
|
IN OUT FILETIME UNALIGNED *lpuTime,
|
||
|
IN OUT LPTSTR lpszBuf,
|
||
|
IN BOOL bShowTime
|
||
|
)
|
||
|
{
|
||
|
FILETIME time;
|
||
|
LPFILETIME lpTime;
|
||
|
BOOL result;
|
||
|
|
||
|
if (lpuTime != NULL) {
|
||
|
time = *lpuTime;
|
||
|
lpTime = &time;
|
||
|
} else {
|
||
|
lpTime = NULL;
|
||
|
}
|
||
|
|
||
|
result = GetTimeInfo( bCreation,
|
||
|
pcpidl,
|
||
|
lpTime,
|
||
|
lpszBuf,
|
||
|
bShowTime );
|
||
|
|
||
|
if (lpuTime != NULL) {
|
||
|
*lpuTime = time;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
#define uaGetControlInfo GetControlInfo
|
||
|
#define uaGetTimeInfo GetTimeInfo
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// IEnumIDList methods
|
||
|
|
||
|
CControlFolderEnum::CControlFolderEnum(STRRET &str, LPCITEMIDLIST pidl, UINT shcontf) :
|
||
|
m_shcontf(shcontf)
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - CControlFolderEnum() called"));
|
||
|
m_cRef = 1;
|
||
|
DllAddRef();
|
||
|
|
||
|
m_bEnumStarted = FALSE;
|
||
|
m_hEnumControl = NULL;
|
||
|
|
||
|
StrRetToBuf(&str, pidl, m_szCachePath, MAX_PATH);
|
||
|
|
||
|
SHGetMalloc(&m_pMalloc); // won't fail
|
||
|
}
|
||
|
|
||
|
CControlFolderEnum::~CControlFolderEnum()
|
||
|
{
|
||
|
Assert(m_cRef == 0); // we should always have a zero ref count here
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - ~CControlFolderEnum() called."));
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
HRESULT CControlFolderEnum_CreateInstance(
|
||
|
LPITEMIDLIST pidl,
|
||
|
UINT shcontf,
|
||
|
LPENUMIDLIST *ppeidl)
|
||
|
|
||
|
{
|
||
|
DebugMsg(DM_TRACE,("cfe - CreateInstance() called."));
|
||
|
|
||
|
if (pidl == NULL)
|
||
|
return HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS);
|
||
|
|
||
|
HRESULT hr;
|
||
|
LPSHELLFOLDER pshf = NULL;
|
||
|
if (FAILED(hr = SHGetDesktopFolder(&pshf)))
|
||
|
return hr;
|
||
|
|
||
|
STRRET name;
|
||
|
hr = pshf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &name);
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
*ppeidl = NULL; // null the out param
|
||
|
|
||
|
CControlFolderEnum *pCFE = new CControlFolderEnum(name, pidl, shcontf);
|
||
|
if (!pCFE)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
*ppeidl = pCFE;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
BOOL GetVersion(LPCONTROLPIDL pcpidl, LPTSTR lpszBuf)
|
||
|
{
|
||
|
Assert(pcpidl != NULL);
|
||
|
LPCTSTR pszLocation = GetStringInfo(pcpidl, SI_LOCATION);
|
||
|
|
||
|
DWORD dwBufLen;
|
||
|
DWORD dwHandle;
|
||
|
BOOL fResult = FALSE;
|
||
|
UINT uLen;
|
||
|
VS_FIXEDFILEINFO *pVersionInfo = NULL;
|
||
|
|
||
|
// Quick copy to handle failure cases
|
||
|
lstrcpy(lpszBuf, g_szUnknownData);
|
||
|
|
||
|
if ((dwBufLen = ::GetFileVersionInfoSize(
|
||
|
(LPTSTR)pszLocation,
|
||
|
&dwHandle)) == 0)
|
||
|
return FALSE;
|
||
|
|
||
|
BYTE *pbData = new BYTE[dwBufLen];
|
||
|
if (pbData == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
if (GetFileVersionInfo((LPTSTR)pszLocation, dwHandle, dwBufLen, pbData))
|
||
|
{
|
||
|
fResult = VerQueryValue(pbData, "\\", (LPVOID*)&pVersionInfo, &uLen);
|
||
|
|
||
|
if (fResult)
|
||
|
{
|
||
|
wsprintf(lpszBuf, "%d,%d,%d,%d",
|
||
|
(pVersionInfo->dwFileVersionMS & 0xffff0000)>>16,
|
||
|
(pVersionInfo->dwFileVersionMS & 0xffff),
|
||
|
(pVersionInfo->dwFileVersionLS & 0xffff0000)>>16,
|
||
|
(pVersionInfo->dwFileVersionLS & 0xffff));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
delete [] pbData;
|
||
|
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
BOOL GetTimeInfo(
|
||
|
BOOL bCreation,
|
||
|
LPCONTROLPIDL pcpidl,
|
||
|
FILETIME* lpTime,
|
||
|
LPTSTR lpszBuf,
|
||
|
BOOL bShowTime)
|
||
|
{
|
||
|
Assert(pcpidl != NULL);
|
||
|
Assert (lpszBuf != NULL);
|
||
|
if (pcpidl == NULL || lpszBuf == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
LPCTSTR pszLocation = GetStringInfo(pcpidl, SI_LOCATION);
|
||
|
|
||
|
BOOL fResult = TRUE;
|
||
|
HANDLE hFile = NULL;
|
||
|
WIN32_FIND_DATA findFileData;
|
||
|
TCHAR szTime[TIMESTAMP_MAXSIZE];
|
||
|
TCHAR szDate[TIMESTAMP_MAXSIZE];
|
||
|
SYSTEMTIME sysTime;
|
||
|
FILETIME localTime;
|
||
|
|
||
|
hFile = FindFirstFile(pszLocation, &findFileData);
|
||
|
|
||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
// Get the creation time and date information.
|
||
|
if (bCreation)
|
||
|
{
|
||
|
*lpTime = findFileData.ftCreationTime;
|
||
|
FileTimeToLocalFileTime(&findFileData.ftCreationTime, &localTime);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lpTime = findFileData.ftLastAccessTime;
|
||
|
FileTimeToLocalFileTime(&findFileData.ftLastAccessTime, &localTime);
|
||
|
}
|
||
|
|
||
|
FileTimeToSystemTime(&localTime, &sysTime);
|
||
|
|
||
|
GetDateFormat(
|
||
|
LOCALE_SYSTEM_DEFAULT,
|
||
|
DATE_SHORTDATE,
|
||
|
&sysTime,
|
||
|
NULL,
|
||
|
szDate,
|
||
|
TIMESTAMP_MAXSIZE);
|
||
|
|
||
|
lstrcpy(lpszBuf, szDate);
|
||
|
|
||
|
if (bShowTime)
|
||
|
{
|
||
|
GetTimeFormat(
|
||
|
LOCALE_SYSTEM_DEFAULT,
|
||
|
TIME_NOSECONDS,
|
||
|
&sysTime,
|
||
|
NULL,
|
||
|
szTime,
|
||
|
TIMESTAMP_MAXSIZE
|
||
|
);
|
||
|
|
||
|
lstrcat(lpszBuf, TEXT(" "));
|
||
|
lstrcat(lpszBuf, szTime);
|
||
|
}
|
||
|
|
||
|
FindClose(hFile);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fResult = FALSE;
|
||
|
lstrcpy(lpszBuf, g_szUnknownData);
|
||
|
lpTime->dwLowDateTime = lpTime->dwHighDateTime = 0;
|
||
|
}
|
||
|
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
LPCONTROLPIDL CreateControlPidl(IMalloc *pmalloc, HANDLE hControl)
|
||
|
{
|
||
|
Assert(pmalloc != NULL);
|
||
|
|
||
|
DWORD dw;
|
||
|
GetControlInfo(hControl, GCI_TOTALFILES, &dw, NULL, 0);
|
||
|
ULONG ulSize = sizeof(CONTROLPIDL) + sizeof(USHORT);
|
||
|
ulSize += (dw - 1) * sizeof(DEPENDENTFILEINFO);
|
||
|
LPCONTROLPIDL pcpidl = (LPCONTROLPIDL)pmalloc->Alloc(ulSize);
|
||
|
|
||
|
if (pcpidl)
|
||
|
{
|
||
|
memset(pcpidl, 0, ulSize);
|
||
|
pcpidl->cb = (USHORT)(ulSize - sizeof(USHORT));
|
||
|
|
||
|
pcpidl->ci.cTotalFiles = (UINT)dw;
|
||
|
uaGetControlInfo(hControl, GCI_TOTALSIZE, &(pcpidl->ci.dwTotalFileSize), NULL, 0);
|
||
|
uaGetControlInfo(hControl, GCI_SIZESAVED, &(pcpidl->ci.dwTotalSizeSaved), NULL, 0);
|
||
|
GetControlInfo(hControl, GCI_NAME, NULL, pcpidl->ci.szName, CONTROLNAME_MAXSIZE);
|
||
|
GetControlInfo(hControl, GCI_FILE, NULL, pcpidl->ci.szFile, MAX_PATH);
|
||
|
GetControlInfo(hControl, GCI_CLSID, NULL, pcpidl->ci.szCLSID, MAX_CLSID_LEN);
|
||
|
GetControlInfo(hControl, GCI_TYPELIBID, NULL, pcpidl->ci.szTypeLibID, MAX_CLSID_LEN);
|
||
|
uaGetTimeInfo(TRUE, pcpidl, &(pcpidl->ci.timeCreation), pcpidl->ci.szCreation, TRUE);
|
||
|
uaGetTimeInfo(FALSE, pcpidl, &(pcpidl->ci.timeLastAccessed), pcpidl->ci.szLastAccess, FALSE);
|
||
|
|
||
|
GetControlInfo(hControl, GCI_CODEBASE, NULL, pcpidl->ci.szCodeBase, INTERNET_MAX_URL_LENGTH);
|
||
|
uaGetControlInfo(hControl, GCI_ISDISTUNIT, &(pcpidl->ci.dwIsDistUnit), NULL, 0);
|
||
|
uaGetControlInfo(hControl, GCI_STATUS, &(pcpidl->ci.dwStatus), NULL, 0);
|
||
|
uaGetControlInfo(hControl, GCI_HAS_ACTIVEX, &(pcpidl->ci.dwHasActiveX), NULL, 0);
|
||
|
uaGetControlInfo(hControl, GCI_HAS_JAVA, &(pcpidl->ci.dwHasJava), NULL, 0);
|
||
|
if (pcpidl->ci.dwIsDistUnit)
|
||
|
{
|
||
|
GetControlInfo(hControl, GCI_DIST_UNIT_VERSION, NULL, pcpidl->ci.szVersion, VERSION_MAXSIZE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetVersion(pcpidl, pcpidl->ci.szVersion);
|
||
|
}
|
||
|
|
||
|
LONG lResult = ERROR_SUCCESS;
|
||
|
DEPENDENTFILEINFO UNALIGNED *pInfo = &(pcpidl->ci.dependentFile);
|
||
|
dw = GetTotalNumOfFiles(pcpidl);
|
||
|
for (UINT iFile = 0; iFile < (UINT)dw; iFile++)
|
||
|
{
|
||
|
DWORD alignedSize = pInfo->dwSize;
|
||
|
lResult = GetControlDependentFile(
|
||
|
iFile,
|
||
|
hControl,
|
||
|
pInfo->szFile,
|
||
|
&alignedSize,
|
||
|
TRUE);
|
||
|
pInfo->dwSize = alignedSize;
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
break;
|
||
|
pInfo = (LPDEPENDENTFILEINFO)(pInfo + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pcpidl;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
//
|
||
|
// IUnknown Methods...
|
||
|
//
|
||
|
HRESULT CControlFolderEnum::QueryInterface(REFIID iid,void **ppv)
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - QueryInterface called."));
|
||
|
|
||
|
if ((iid == IID_IEnumIDList) || (iid == IID_IUnknown))
|
||
|
{
|
||
|
*ppv = (void *)this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
*ppv = NULL;
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
ULONG CControlFolderEnum::AddRef(void)
|
||
|
{
|
||
|
return ++m_cRef;
|
||
|
}
|
||
|
|
||
|
ULONG CControlFolderEnum::Release(void)
|
||
|
{
|
||
|
if (--m_cRef)
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CControlFolderEnum::Next(
|
||
|
ULONG celt,
|
||
|
LPITEMIDLIST *rgelt,
|
||
|
ULONG *pceltFetched)
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - Next() called."));
|
||
|
|
||
|
// If asking for stuff we don't have, say we don't have any
|
||
|
if (!(m_shcontf & SHCONTF_NONFOLDERS))
|
||
|
return S_FALSE;
|
||
|
|
||
|
LONG lres = ERROR_SUCCESS;
|
||
|
HANDLE hControl = NULL;
|
||
|
LPCONTROLPIDL pcpidl = NULL;
|
||
|
|
||
|
lres = (!m_bEnumStarted ?
|
||
|
FindFirstControl(m_hEnumControl, hControl, m_szCachePath) :
|
||
|
FindNextControl(m_hEnumControl, hControl));
|
||
|
|
||
|
if (pceltFetched)
|
||
|
*pceltFetched = (lres == ERROR_SUCCESS ? 1 : 0);
|
||
|
|
||
|
if (lres != ERROR_SUCCESS)
|
||
|
goto EXIT_NEXT;
|
||
|
|
||
|
pcpidl = CreateControlPidl(m_pMalloc, hControl);
|
||
|
if (pcpidl == NULL)
|
||
|
{
|
||
|
lres = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto EXIT_NEXT;
|
||
|
}
|
||
|
|
||
|
m_bEnumStarted = TRUE;
|
||
|
rgelt[0] = (LPITEMIDLIST)pcpidl;
|
||
|
|
||
|
EXIT_NEXT:
|
||
|
|
||
|
ReleaseControlHandle(hControl);
|
||
|
|
||
|
if (lres != ERROR_SUCCESS)
|
||
|
{
|
||
|
if (pcpidl != NULL)
|
||
|
{
|
||
|
m_pMalloc->Free(pcpidl);
|
||
|
pcpidl = NULL;
|
||
|
}
|
||
|
FindControlClose(m_hEnumControl);
|
||
|
m_bEnumStarted = FALSE;
|
||
|
rgelt[0] = NULL;
|
||
|
}
|
||
|
|
||
|
return HRESULT_FROM_WIN32(lres);
|
||
|
}
|
||
|
|
||
|
HRESULT CControlFolderEnum::Skip(ULONG celt)
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - Skip() called."));
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
HRESULT CControlFolderEnum::Reset()
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - Reset() called."));
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
HRESULT CControlFolderEnum::Clone(IEnumIDList **ppenum)
|
||
|
{
|
||
|
DebugMsg(DM_TRACE, TEXT("cfe - Clone() called."));
|
||
|
return E_NOTIMPL;
|
||
|
}
|