Leaked source code of windows server 2003
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.

320 lines
10 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // File: tasks.cpp
  6. // App Management tasks running on the secondary thread
  7. //
  8. // History:
  9. // 2-26-98 by dli implemented CAppUemInfoTask
  10. //------------------------------------------------------------------------
  11. #include "priv.h"
  12. #include "shguidp.h"
  13. #include "uemapp.h"
  14. #include "appsize.h"
  15. #include "findapp.h"
  16. #include "tasks.h"
  17. #include "slowfind.h"
  18. #include "dump.h"
  19. #include "util.h"
  20. // Utility function to get times used or last used time for "exe" files
  21. void ExtractExeInfo(LPCTSTR pszExe, PSLOWAPPINFO psai, BOOL bNoImageChange)
  22. {
  23. ASSERT(IS_VALID_STRING_PTR(pszExe, -1));
  24. // Got to have a legal psai
  25. ASSERT(psai);
  26. // Get the "times used" info
  27. UEMINFO uei = {0};
  28. uei.cbSize = SIZEOF(uei);
  29. uei.dwMask = UEIM_HIT;
  30. if (SUCCEEDED(UEMQueryEvent(&UEMIID_SHELL, UEME_RUNPATH, (WPARAM)-1, (LPARAM)pszExe, &uei)))
  31. {
  32. if (uei.cHit > psai->iTimesUsed)
  33. psai->iTimesUsed = uei.cHit;
  34. }
  35. // Get the most recent access time
  36. HANDLE hFile = CreateFile(pszExe, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  37. NULL, OPEN_EXISTING, 0, NULL );
  38. if( INVALID_HANDLE_VALUE != hFile )
  39. {
  40. FILETIME ftCreate, ftAccessed, ftWrite;
  41. if (GetFileTime(hFile, &ftCreate, &ftAccessed, &ftWrite))
  42. {
  43. // Is the creation and accessed dates identical, and is the
  44. // UEM's statistic useless?
  45. if (0 == CompareFileTime(&ftAccessed, &ftCreate) &&
  46. 0 == psai->ftLastUsed.dwHighDateTime)
  47. {
  48. // Yes; then it doesn't look like anyone has used it
  49. psai->ftLastUsed.dwHighDateTime = NOTUSED_HIGHDATETIME;
  50. psai->ftLastUsed.dwLowDateTime = NOTUSED_LOWDATETIME;
  51. if (!bNoImageChange && (psai->pszImage == NULL))
  52. SHStrDup(pszExe, &psai->pszImage);
  53. }
  54. else if (CompareFileTime(&ftAccessed, &psai->ftLastUsed) > 0)
  55. {
  56. // No; someone must have used this program
  57. psai->ftLastUsed = ftAccessed;
  58. if (!bNoImageChange)
  59. {
  60. // If there was an exe file for the icon, release that
  61. if (psai->pszImage)
  62. SHFree(psai->pszImage);
  63. // Set the icon image of this app to this exe's icon
  64. // because this exe is the most recently used one.
  65. SHStrDup(pszExe, &psai->pszImage);
  66. }
  67. }
  68. }
  69. CloseHandle(hFile);
  70. }
  71. }
  72. const static struct {
  73. LPTSTR szAppName;
  74. LPTSTR szExeName;
  75. } s_rgAppHacks[] = {
  76. { TEXT("Microsoft Office"), TEXT("msoffice.exe")},
  77. };
  78. //--------------------------------------------------------------------------------
  79. // CAppInfoFinder class
  80. //--------------------------------------------------------------------------------
  81. static const WCHAR sc_wszStarDotExe[] = L"*.exe";
  82. // Use the TreeWalker to find the application "exe" file
  83. class CAppInfoFinder : public CAppFolderSize
  84. {
  85. public:
  86. CAppInfoFinder(PSLOWAPPINFO psai, BOOL fSize, LPCTSTR pszHintExe, BOOL fNoImageChange);
  87. // *** IShellTreeWalkerCallBack methods (override) ***
  88. STDMETHOD(FoundFile) (LPCWSTR pwszFolder, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
  89. HRESULT SearchInFolder(LPCTSTR pszFolder);
  90. protected:
  91. PSLOWAPPINFO _psai;
  92. BOOL _fComputeSize; // Compute size or not
  93. BOOL _fNoImageChange; // Do not change image from now on.
  94. TCHAR _szHintExe[MAX_PATH];
  95. };
  96. // constructor
  97. CAppInfoFinder::CAppInfoFinder(PSLOWAPPINFO psai, BOOL fSize, LPCTSTR pszHintExe, BOOL fNoImageChange) :
  98. _fComputeSize(fSize), _fNoImageChange(fNoImageChange), _psai(psai), CAppFolderSize(&psai->ullSize)
  99. {
  100. if (pszHintExe)
  101. {
  102. lstrcpyn(_szHintExe, pszHintExe, ARRAYSIZE(_szHintExe));
  103. }
  104. }
  105. /*-------------------------------------------------------------------------
  106. Purpose: IShellTreeWalkerCallBack::FoundFile
  107. Extracts the exe info that we want if the given file matches
  108. an exe spec. The info is stored in the _psai member variable.
  109. */
  110. HRESULT CAppInfoFinder::FoundFile(LPCWSTR pwszFile, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfdw)
  111. {
  112. HRESULT hres = S_OK;
  113. ASSERT(IS_VALID_STRING_PTRW(pwszFile, -1));
  114. if (PathMatchSpecW(pwfdw->cFileName, sc_wszStarDotExe))
  115. {
  116. TCHAR szPath[MAX_PATH];
  117. TraceMsg(TF_SLOWFIND, "Found Exe File: %s", pwszFile);
  118. SHUnicodeToTChar(pwszFile, szPath, ARRAYSIZE(szPath));
  119. if (!PathIsSetup(szPath, 2))
  120. {
  121. ExtractExeInfo(szPath, _psai, _fNoImageChange);
  122. if (_szHintExe[0] != TEXT('\0'))
  123. {
  124. // Does this exe match our app's Hint icon exe?
  125. if (!lstrcmpi(_szHintExe, PathFindFileName(szPath)))
  126. {
  127. // Yes, Bingo!! Use this icon.
  128. // If there was an exe file for the icon, release that
  129. if (_psai->pszImage)
  130. SHFree(_psai->pszImage);
  131. // Set the icon image of this app to this exe's icon
  132. SHStrDup(szPath, &_psai->pszImage);
  133. _fNoImageChange = TRUE;
  134. }
  135. }
  136. }
  137. }
  138. if (_fComputeSize)
  139. hres = CAppFolderSize::FoundFile(pwszFile, ptws, pwfdw);
  140. return hres;
  141. }
  142. /*-------------------------------------------------------------------------
  143. Purpose: Method to kick off the tree walk, starting at pszFolder.
  144. */
  145. HRESULT CAppInfoFinder::SearchInFolder(LPCTSTR pszFolder)
  146. {
  147. HRESULT hres = E_FAIL;
  148. WCHAR wszDir[MAX_PATH];
  149. SHTCharToUnicode(pszFolder, wszDir, SIZECHARS(wszDir));
  150. if (_pstw)
  151. hres = _pstw->WalkTree(0, wszDir, NULL, 0, SAFECAST(this, IShellTreeWalkerCallBack *));
  152. return hres;
  153. }
  154. //--------------------------------------------------------------------------------
  155. // CAppInfoFinderSM class
  156. //--------------------------------------------------------------------------------
  157. // Use the TreeWalker to find the application "exe" file
  158. class CAppInfoFinderSM : public CStartMenuAppFinder
  159. {
  160. public:
  161. CAppInfoFinderSM(LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai);
  162. // *** IShellTreeWalkerCallBack methods ***
  163. virtual STDMETHODIMP FoundFile(LPCWSTR pwszFolder, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd);
  164. protected:
  165. PSLOWAPPINFO _psai;
  166. TCHAR _szFakeFolder[MAX_PATH];
  167. };
  168. // constructor
  169. CAppInfoFinderSM::CAppInfoFinderSM(LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai) :
  170. _psai(psai),CStartMenuAppFinder(pszFullName, pszShortName, _szFakeFolder)
  171. {
  172. }
  173. /*-------------------------------------------------------------------------
  174. Purpose: IShellTreeWalkerCallBack::FoundFile
  175. Extracts the exe info that we want if the given file matches
  176. an exe spec. The info is stored in the _psai member variable.
  177. */
  178. HRESULT CAppInfoFinderSM::FoundFile(LPCWSTR pwszFile, TREEWALKERSTATS *ptws, WIN32_FIND_DATAW * pwfd)
  179. {
  180. TCHAR szLnkFile[MAX_PATH];
  181. ASSERT(IS_VALID_STRING_PTRW(pwszFile, -1));
  182. SHUnicodeToTChar(pwszFile, szLnkFile, ARRAYSIZE(szLnkFile));
  183. TraceMsg(TF_SLOWFIND, "CSMAF:Lnk %s -- %s %s", _pszFullName, szLnkFile);
  184. if (!_MatchSMLinkWithApp(szLnkFile))
  185. return S_OK;
  186. TCHAR szTargetFile[MAX_PATH];
  187. HRESULT hresT = GetShortcutTarget(szLnkFile, szTargetFile, ARRAYSIZE(szTargetFile));
  188. if ((S_FALSE == hresT) || ((S_OK == hresT) && !PathIsRoot(szTargetFile) && !PathIsUnderWindows(szTargetFile) && !PathIsSetup(szTargetFile, 1)))
  189. {
  190. LPCTSTR pszName = PathFindFileName(szTargetFile);
  191. if (PathMatchSpec(pszName, sc_wszStarDotExe))
  192. ExtractExeInfo(szTargetFile, _psai, FALSE);
  193. }
  194. return S_OK;
  195. }
  196. LPTSTR LookUpHintExes(LPCTSTR pszAppName, LPTSTR pszHintExe, DWORD cbHintExe)
  197. {
  198. // Open the reg key
  199. HKEY hkeyIconHints = NULL;
  200. LPTSTR pszRet = NULL;
  201. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Management\\Icon Hints")
  202. , 0, KEY_READ, &hkeyIconHints))
  203. {
  204. DWORD dwType;
  205. // Look up in the registry for this cpl name
  206. if ((ERROR_SUCCESS == SHQueryValueEx(hkeyIconHints, pszAppName, NULL, &dwType, pszHintExe, &cbHintExe))
  207. && (dwType == REG_SZ))
  208. {
  209. pszRet = pszHintExe;
  210. }
  211. RegCloseKey(hkeyIconHints);
  212. }
  213. return pszRet;
  214. }
  215. // use the tree walker to find the "exe" file for the application
  216. HRESULT FindAppInfo(LPCTSTR pszFolder, LPCTSTR pszFullName, LPCTSTR pszShortName, PSLOWAPPINFO psai, BOOL bChanged)
  217. {
  218. // If there is no output string, a folder and a name, we can't do anything
  219. ASSERT(IS_VALID_WRITE_PTR(psai, SLOWAPPINFO));
  220. if (pszFolder)
  221. {
  222. // We only compute sizes for locally installed apps and apps installed
  223. // on fixed drives. Ex: On board or external hard drives.
  224. // We purposely not compute size for network apps, apps on the CD ROMs and so on
  225. BOOL bGetSize = bChanged && PathIsLocalAndFixed(pszFolder);
  226. TCHAR szHintExe[MAX_PATH];
  227. LPTSTR pszHintExe = LookUpHintExes(pszFullName, szHintExe, SIZEOF(szHintExe));
  228. CAppInfoFinder * paef = new CAppInfoFinder(psai, bGetSize, pszHintExe, !bChanged);
  229. if (paef)
  230. {
  231. if (SUCCEEDED(paef->Initialize()))
  232. paef->SearchInFolder(pszFolder);
  233. paef->Release();
  234. }
  235. }
  236. if (bChanged)
  237. {
  238. CAppInfoFinderSM * paifsm = new CAppInfoFinderSM(pszFullName, pszShortName, psai);
  239. if (paifsm)
  240. {
  241. if (SUCCEEDED(paifsm->Initialize()))
  242. {
  243. TCHAR szStartMenu[MAX_PATH];
  244. if (SHGetSpecialFolderPath(NULL, szStartMenu, CSIDL_COMMON_PROGRAMS, FALSE))
  245. paifsm->SearchInFolder(szStartMenu);
  246. if (SHGetSpecialFolderPath(NULL, szStartMenu, CSIDL_PROGRAMS, FALSE))
  247. paifsm->SearchInFolder(szStartMenu);
  248. }
  249. paifsm->Release();
  250. }
  251. }
  252. return S_OK;
  253. }