|
|
//---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation
//
// File: tasks.cpp
// App Management tasks running on the secondary thread
//
// History:
// 2-26-98 by dli implemented CAppUemInfoTask
//------------------------------------------------------------------------
#include "priv.h"
#include "shguidp.h"
#include "uemapp.h"
#include "appsize.h"
#include "findapp.h"
#include "tasks.h"
#include "slowfind.h"
#include "dump.h"
#include "util.h"
// Utility function to get times used or last used time for "exe" files
void ExtractExeInfo(LPCTSTR pszExe, PSLOWAPPINFO psai, BOOL bNoImageChange) { ASSERT(IS_VALID_STRING_PTR(pszExe, -1)); // Got to have a legal psai
ASSERT(psai);
// Get the "times used" info
UEMINFO uei = {0}; uei.cbSize = SIZEOF(uei); uei.dwMask = UEIM_HIT; if (SUCCEEDED(UEMQueryEvent(&UEMIID_SHELL, UEME_RUNPATH, (WPARAM)-1, (LPARAM)pszExe, &uei))) { if (uei.cHit > psai->iTimesUsed) psai->iTimesUsed = uei.cHit; }
// Get the most recent access time
HANDLE hFile = CreateFile(pszExe, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL ); if( INVALID_HANDLE_VALUE != hFile ) { FILETIME ftCreate, ftAccessed, ftWrite; if (GetFileTime(hFile, &ftCreate, &ftAccessed, &ftWrite)) { // Is the creation and accessed dates identical, and is the
// UEM's statistic useless?
if (0 == CompareFileTime(&ftAccessed, &ftCreate) && 0 == psai->ftLastUsed.dwHighDateTime) { // Yes; then it doesn't look like anyone has used it
psai->ftLastUsed.dwHighDateTime = NOTUSED_HIGHDATETIME; psai->ftLastUsed.dwLowDateTime = NOTUSED_LOWDATETIME; if (!bNoImageChange && (psai->pszImage == NULL)) SHStrDup(pszExe, &psai->pszImage); } else if (CompareFileTime(&ftAccessed, &psai->ftLastUsed) > 0) { // No; someone must have used this program
psai->ftLastUsed = ftAccessed;
if (!bNoImageChange) { // If there was an exe file for the icon, release that
if (psai->pszImage) SHFree(psai->pszImage);
// Set the icon image of this app to this exe's icon
// because this exe is the most recently used one.
SHStrDup(pszExe, &psai->pszImage); } } }
CloseHandle(hFile); } }
const static struct { LPTSTR szAppName; LPTSTR szExeName; } s_rgAppHacks[] = { { TEXT("Microsoft Office"), TEXT("msoffice.exe")}, };
//--------------------------------------------------------------------------------
// CAppInfoFinder class
//--------------------------------------------------------------------------------
static const WCHAR sc_wszStarDotExe[] = L"*.exe";
// Use the TreeWalker to find the application "exe" file
class CAppInfoFinder : public CAppFolderSize { public: CAppInfoFinder(PSLOWAPPINFO psai, BOOL fSize, LPCTSTR pszHintExe, BOOL fNoImageChange); // *** IShellTreeWalkerCallBack methods (override) ***
STDMETHOD(FoundFile) (LPCWSTR pwszFolder, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
HRESULT SearchInFolder(LPCTSTR pszFolder);
protected: PSLOWAPPINFO _psai; BOOL _fComputeSize; // Compute size or not
BOOL _fNoImageChange; // Do not change image from now on.
TCHAR _szHintExe[MAX_PATH]; };
// constructor
CAppInfoFinder::CAppInfoFinder(PSLOWAPPINFO psai, BOOL fSize, LPCTSTR pszHintExe, BOOL fNoImageChange) : _fComputeSize(fSize), _fNoImageChange(fNoImageChange), _psai(psai), CAppFolderSize(&psai->ullSize) { if (pszHintExe) { lstrcpyn(_szHintExe, pszHintExe, ARRAYSIZE(_szHintExe)); } }
/*-------------------------------------------------------------------------
Purpose: IShellTreeWalkerCallBack::FoundFile
Extracts the exe info that we want if the given file matches an exe spec. The info is stored in the _psai member variable. */ HRESULT CAppInfoFinder::FoundFile(LPCWSTR pwszFile, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfdw) { HRESULT hres = S_OK;
ASSERT(IS_VALID_STRING_PTRW(pwszFile, -1));
if (PathMatchSpecW(pwfdw->cFileName, sc_wszStarDotExe)) { TCHAR szPath[MAX_PATH]; TraceMsg(TF_SLOWFIND, "Found Exe File: %s", pwszFile); SHUnicodeToTChar(pwszFile, szPath, ARRAYSIZE(szPath));
if (!PathIsSetup(szPath, 2)) { ExtractExeInfo(szPath, _psai, _fNoImageChange);
if (_szHintExe[0] != TEXT('\0')) { // Does this exe match our app's Hint icon exe?
if (!lstrcmpi(_szHintExe, PathFindFileName(szPath))) { // Yes, Bingo!! Use this icon.
// If there was an exe file for the icon, release that
if (_psai->pszImage) SHFree(_psai->pszImage);
// Set the icon image of this app to this exe's icon
SHStrDup(szPath, &_psai->pszImage);
_fNoImageChange = TRUE; } } } }
if (_fComputeSize) hres = CAppFolderSize::FoundFile(pwszFile, ptws, pwfdw); return hres; }
/*-------------------------------------------------------------------------
Purpose: Method to kick off the tree walk, starting at pszFolder. */ HRESULT CAppInfoFinder::SearchInFolder(LPCTSTR pszFolder) { HRESULT hres = E_FAIL; WCHAR wszDir[MAX_PATH];
SHTCharToUnicode(pszFolder, wszDir, SIZECHARS(wszDir));
if (_pstw) hres = _pstw->WalkTree(0, wszDir, NULL, 0, SAFECAST(this, IShellTreeWalkerCallBack *));
return hres; }
//--------------------------------------------------------------------------------
// CAppInfoFinderSM class
//--------------------------------------------------------------------------------
// Use the TreeWalker to find the application "exe" file
class CAppInfoFinderSM : public CStartMenuAppFinder { public: CAppInfoFinderSM(LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai); // *** IShellTreeWalkerCallBack methods ***
virtual STDMETHODIMP FoundFile(LPCWSTR pwszFolder, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
protected: PSLOWAPPINFO _psai; TCHAR _szFakeFolder[MAX_PATH]; };
// constructor
CAppInfoFinderSM::CAppInfoFinderSM(LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai) : _psai(psai),CStartMenuAppFinder(pszFullName, pszShortName, _szFakeFolder) { }
/*-------------------------------------------------------------------------
Purpose: IShellTreeWalkerCallBack::FoundFile
Extracts the exe info that we want if the given file matches an exe spec. The info is stored in the _psai member variable. */ HRESULT CAppInfoFinderSM::FoundFile(LPCWSTR pwszFile, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd) { TCHAR szLnkFile[MAX_PATH];
ASSERT(IS_VALID_STRING_PTRW(pwszFile, -1));
SHUnicodeToTChar(pwszFile, szLnkFile, ARRAYSIZE(szLnkFile)); TraceMsg(TF_SLOWFIND, "CSMAF:Lnk %s -- %s %s", _pszFullName, szLnkFile);
if (!_MatchSMLinkWithApp(szLnkFile)) return S_OK;
TCHAR szTargetFile[MAX_PATH]; HRESULT hresT = GetShortcutTarget(szLnkFile, szTargetFile, ARRAYSIZE(szTargetFile)); if ((S_FALSE == hresT) || ((S_OK == hresT) && !PathIsRoot(szTargetFile) && !PathIsUnderWindows(szTargetFile) && !PathIsSetup(szTargetFile, 1))) { LPCTSTR pszName = PathFindFileName(szTargetFile); if (PathMatchSpec(pszName, sc_wszStarDotExe)) ExtractExeInfo(szTargetFile, _psai, FALSE); }
return S_OK; }
LPTSTR LookUpHintExes(LPCTSTR pszAppName, LPTSTR pszHintExe, DWORD cbHintExe) { // Open the reg key
HKEY hkeyIconHints = NULL; LPTSTR pszRet = NULL; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Management\\Icon Hints") , 0, KEY_READ, &hkeyIconHints)) { DWORD dwType; // Look up in the registry for this cpl name
if ((ERROR_SUCCESS == SHQueryValueEx(hkeyIconHints, pszAppName, NULL, &dwType, pszHintExe, &cbHintExe)) && (dwType == REG_SZ)) { pszRet = pszHintExe; }
RegCloseKey(hkeyIconHints); }
return pszRet; }
// use the tree walker to find the "exe" file for the application
HRESULT FindAppInfo(LPCTSTR pszFolder, LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai, BOOL bChanged) { // If there is no output string, a folder and a name, we can't do anything
ASSERT(IS_VALID_WRITE_PTR(psai, SLOWAPPINFO)); if (pszFolder) { // We only compute sizes for locally installed apps and apps installed
// on fixed drives. Ex: On board or external hard drives.
// We purposely not compute size for network apps, apps on the CD ROMs and so on
BOOL bGetSize = bChanged && PathIsLocalAndFixed(pszFolder); TCHAR szHintExe[MAX_PATH]; LPTSTR pszHintExe = LookUpHintExes(pszFullName, szHintExe, SIZEOF(szHintExe)); CAppInfoFinder * paef = new CAppInfoFinder(psai, bGetSize, pszHintExe, !bChanged); if (paef) { if (SUCCEEDED(paef->Initialize())) paef->SearchInFolder(pszFolder); paef->Release(); } }
if (bChanged) { CAppInfoFinderSM * paifsm = new CAppInfoFinderSM(pszFullName, pszShortName, psai); if (paifsm) { if (SUCCEEDED(paifsm->Initialize())) { TCHAR szStartMenu[MAX_PATH]; if (SHGetSpecialFolderPath(NULL, szStartMenu, CSIDL_COMMON_PROGRAMS, FALSE)) paifsm->SearchInFolder(szStartMenu);
if (SHGetSpecialFolderPath(NULL, szStartMenu, CSIDL_PROGRAMS, FALSE)) paifsm->SearchInFolder(szStartMenu); } paifsm->Release(); } } return S_OK; }
|