Source code of Windows XP (NT5)
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.

286 lines
7.8 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: delexdl.cpp
  6. //
  7. // Description:
  8. //
  9. // Function exported by IUEngine.dll to do extra work upon
  10. // the engine Dll gets loaded, including:
  11. // (1) clean up old download folders
  12. // (2) download security data
  13. //
  14. //=======================================================================
  15. #include "iuengine.h"
  16. #include <wuiutest.h>
  17. #include <fileutil.h>
  18. #include <stringutil.h>
  19. #include <trust.h>
  20. #include <download.h>
  21. #include <freelog.h>
  22. #include <advpub.h> // for ExtractFiles
  23. #include <WaitUtil.h>
  24. #include <urllogging.h>
  25. #include <safefile.h>
  26. #define GotoCleanUpIfAskedQuit if (WaitForSingleObject(g_evtNeedToQuit, 0) == WAIT_OBJECT_0) {goto CleanUp;}
  27. //
  28. // Default expiration time is 30 days (30 days * 24 hrs * 60 min * 60 sec)
  29. //
  30. // Since the default time has a very large granularity, we don't account for the
  31. // documented differences between FILETIME for different platforms and file systems
  32. // (see MSDN for details).
  33. //
  34. const DWORD DEFAULT_EXPIRED_SECONDS = 2592000;
  35. const int NanoSec100PerSec = 10000000; // number of 100 nanoseconds per second (FILETIME unit)
  36. DWORD WINAPI DeleteFoldersThreadProc(LPVOID lpv);
  37. void AsyncDeleteExpiredDownloadFolders(void);
  38. //=========================================================================
  39. //
  40. // exported public function called by control after the engine loaded.
  41. //
  42. //=========================================================================
  43. void WINAPI AsyncExtraWorkUponEngineLoad()
  44. {
  45. //
  46. // Only do this the first time we are loaded (not for every client / instance)
  47. //
  48. if (0 == InterlockedExchange(&g_lDoOnceOnLoadGuard, 1))
  49. {
  50. AsyncDeleteExpiredDownloadFolders();
  51. }
  52. }
  53. //-------------------------------------------------------------------------
  54. //
  55. // Creates a thread that searches WUTemp folders for old downloaded content
  56. // that has not been deleted.
  57. //
  58. // Since it is not critical that this function succeed, we don't return
  59. // errors.
  60. //
  61. //-------------------------------------------------------------------------
  62. void AsyncDeleteExpiredDownloadFolders()
  63. {
  64. LOG_Block("DeleteExpiredDownloadFolders");
  65. DWORD dwThreadId;
  66. HANDLE hThread;
  67. //
  68. // Create thread and let it run until it finishes or g_evtNeedToQuit gets signaled
  69. //
  70. InterlockedIncrement(&g_lThreadCounter);
  71. hThread = CreateThread(NULL, 0, DeleteFoldersThreadProc, (LPVOID) NULL, 0, &dwThreadId);
  72. if (NULL == hThread)
  73. {
  74. LOG_ErrorMsg(GetLastError());
  75. InterlockedDecrement(&g_lThreadCounter);
  76. return;
  77. }
  78. CloseHandle(hThread);
  79. }
  80. //-------------------------------------------------------------------------
  81. //
  82. // DeleteFoldersThreadProc()
  83. //
  84. // thread function to clean up expired download folders
  85. //
  86. //-------------------------------------------------------------------------
  87. DWORD WINAPI DeleteFoldersThreadProc(LPVOID /*lpv*/)
  88. {
  89. LOG_Block("DeleteFoldersThreadProc");
  90. DWORD dwExpiredSeconds = DEFAULT_EXPIRED_SECONDS;
  91. HRESULT hr;
  92. FILETIME ftExpired;
  93. ULARGE_INTEGER u64ft;
  94. ULARGE_INTEGER u64Offset;
  95. DWORD dwRet;
  96. #if defined(__WUIUTEST)
  97. // Override DEFAULT_EXPIRED_SECONDS
  98. HKEY hKey;
  99. int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
  100. if (ERROR_SUCCESS == error)
  101. {
  102. DWORD dwSize = sizeof(DWORD);
  103. DWORD dwValue;
  104. error = RegQueryValueEx(hKey, REGVAL_DEFAULT_EXPIRED_SECONDS, 0, 0, (LPBYTE) &dwExpiredSeconds, &dwSize);
  105. if (ERROR_SUCCESS == error)
  106. {
  107. LOG_Driver(_T("DEFAULT_EXPIRED_SECONDS changed to %d seconds"), dwExpiredSeconds);
  108. }
  109. RegCloseKey(hKey);
  110. }
  111. #endif
  112. GetSystemTimeAsFileTime(&ftExpired);
  113. u64ft.u.LowPart = ftExpired.dwLowDateTime;
  114. u64ft.u.HighPart = ftExpired.dwHighDateTime;
  115. u64Offset.u.LowPart = NanoSec100PerSec;
  116. u64Offset.u.HighPart = 0;
  117. u64Offset.QuadPart *= dwExpiredSeconds;
  118. u64ft.QuadPart -= u64Offset.QuadPart;
  119. ftExpired.dwLowDateTime = u64ft.u.LowPart;
  120. ftExpired.dwHighDateTime = u64ft.u.HighPart;
  121. //
  122. // Get list of drives we will search
  123. //
  124. TCHAR szDriveStrBuffer[MAX_PATH + 2];
  125. TCHAR szWUTempPath[MAX_PATH];
  126. WIN32_FIND_DATA fd;
  127. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  128. LPTSTR pszRootPathName;
  129. //
  130. // If quit was signaled before we were scheduled, just bail
  131. //
  132. GotoCleanUpIfAskedQuit;
  133. //
  134. // Make sure we are double-null terminated by zeroing buffer and lying about size
  135. //
  136. ZeroMemory(szDriveStrBuffer, sizeof(szDriveStrBuffer));
  137. if (0 == (dwRet = GetLogicalDriveStrings(ARRAYSIZE(szDriveStrBuffer) - 2, (LPTSTR) szDriveStrBuffer))
  138. || (ARRAYSIZE(szDriveStrBuffer) - 2) < dwRet)
  139. {
  140. LOG_ErrorMsg(GetLastError());
  141. goto CleanUp;
  142. }
  143. for (pszRootPathName = szDriveStrBuffer; NULL != *pszRootPathName; pszRootPathName += lstrlen(pszRootPathName) + 1)
  144. {
  145. //
  146. // Only look for szIUTemp on fixed drives
  147. //
  148. if (DRIVE_FIXED == GetDriveType(pszRootPathName))
  149. {
  150. //
  151. // Create the dir path
  152. //
  153. hr = StringCchCopyEx(szWUTempPath, ARRAYSIZE(szWUTempPath), pszRootPathName,
  154. NULL, NULL, MISTSAFE_STRING_FLAGS);
  155. if (FAILED(hr))
  156. {
  157. LOG_ErrorMsg(hr);
  158. continue;
  159. }
  160. hr = PathCchAppend(szWUTempPath, ARRAYSIZE(szWUTempPath), IU_WUTEMP);
  161. if (FAILED(hr))
  162. {
  163. LOG_ErrorMsg(hr);
  164. continue;
  165. }
  166. DWORD dwAttr;
  167. dwAttr = GetFileAttributes(szWUTempPath);
  168. if (dwAttr != 0xFFFFFFFF && (FILE_ATTRIBUTE_DIRECTORY & dwAttr))
  169. {
  170. //
  171. // Look for directories older than ftExpired
  172. //
  173. // NOTE:When we add support for AU and/or Drizzle we should add a
  174. // file to the folder to override the default delete time.
  175. // We should synchronize access to this file by opening exclusive.
  176. //
  177. // Find the first file in the directory
  178. hr = PathCchAppend(szWUTempPath, ARRAYSIZE(szWUTempPath), _T("\\*.*"));
  179. if (FAILED(hr))
  180. {
  181. LOG_ErrorMsg(hr);
  182. continue;
  183. }
  184. if (INVALID_HANDLE_VALUE == (hFindFile = FindFirstFile(szWUTempPath, &fd)))
  185. {
  186. LOG_ErrorMsg(GetLastError());
  187. continue;
  188. }
  189. do
  190. {
  191. if (
  192. (CSTR_EQUAL == CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE,
  193. fd.cFileName, -1, TEXT("."), -1)) ||
  194. (CSTR_EQUAL == CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE,
  195. fd.cFileName, -1, TEXT(".."), -1))
  196. ) continue;
  197. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  198. {
  199. //
  200. // If directory creation time < expired time delete the directory
  201. //
  202. if (-1 == CompareFileTime(&fd.ftCreationTime, &ftExpired))
  203. {
  204. TCHAR szDirPath[MAX_PATH];
  205. hr = StringCchCopyEx(szDirPath, ARRAYSIZE(szDirPath), pszRootPathName,
  206. NULL, NULL, MISTSAFE_STRING_FLAGS);
  207. if (FAILED(hr))
  208. {
  209. LOG_ErrorMsg(hr);
  210. continue;
  211. }
  212. hr = PathCchAppend(szDirPath, ARRAYSIZE(szDirPath), IU_WUTEMP);
  213. if (FAILED(hr))
  214. {
  215. LOG_ErrorMsg(hr);
  216. continue;
  217. }
  218. hr = PathCchAppend(szDirPath, ARRAYSIZE(szDirPath), fd.cFileName);
  219. if (FAILED(hr))
  220. {
  221. LOG_ErrorMsg(hr);
  222. continue;
  223. }
  224. (void) SafeDeleteFolderAndContents(szDirPath, SDF_DELETE_READONLY_FILES | SDF_CONTINUE_IF_ERROR);
  225. }
  226. }
  227. GotoCleanUpIfAskedQuit;
  228. } while (FindNextFile(hFindFile, &fd));// Find the next entry
  229. }
  230. }
  231. }
  232. CleanUp:
  233. if (INVALID_HANDLE_VALUE != hFindFile)
  234. {
  235. FindClose(hFindFile);
  236. }
  237. InterlockedDecrement(&g_lThreadCounter);
  238. return 0;
  239. }