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.

425 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: wudirectory.cpp
  8. // Desc: This is the definition file that implements function(s)
  9. // related to find out where to get the Critical Fix cab file.
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "pch.h"
  13. #pragma hdrstop
  14. TCHAR g_szWUDir[MAX_PATH+1] = _T("\0"); //Path to windows update directory
  15. const TCHAR CABS_DIR[] = _T("cabs");
  16. const TCHAR RTF_DIR[] = _T("RTF");
  17. const TCHAR EULA_DIR[] = _T("EULA");
  18. const TCHAR DETAILS_DIR[] = _T("Details");
  19. const TCHAR C_DOWNLD_DIR[] = _T("wuaudnld.tmp");
  20. BOOL AUDelFileOrDir(LPCTSTR szFileOrDir)
  21. {
  22. if (NULL == szFileOrDir)
  23. {
  24. SetLastError(ERROR_INVALID_PARAMETER);
  25. return FALSE;
  26. }
  27. BOOL fIsDir = TRUE;
  28. if (fFileExists(szFileOrDir, &fIsDir))
  29. {
  30. if (fIsDir)
  31. {
  32. if (DelDir(szFileOrDir))
  33. {
  34. return RemoveDirectory(szFileOrDir);
  35. }
  36. return FALSE;
  37. }
  38. else
  39. {
  40. return DeleteFile(szFileOrDir);
  41. }
  42. }
  43. SetLastError(ERROR_FILE_NOT_FOUND);
  44. return FALSE;
  45. }
  46. ////////////////////////////////////////////////////////////////////////
  47. // Create the WU directory if it doesnt already exist
  48. // return FALSE if failed
  49. /////////////////////////////////////////////////////////////////////////
  50. BOOL CreateWUDirectory(BOOL fGetPathOnly)
  51. {
  52. BOOL fRet = FALSE;
  53. static BOOL fWUDirectoryExists = FALSE;
  54. // WindowsUpdate Directory already exists
  55. if (fWUDirectoryExists)
  56. {
  57. fRet = TRUE;
  58. goto done;
  59. }
  60. //Get the path to the windows update directory
  61. if( !GetWUDirectory(g_szWUDir, ARRAYSIZE(g_szWUDir)))
  62. {
  63. goto done;
  64. }
  65. //If we need to set the acls to the directory
  66. if(!fGetPathOnly)
  67. {
  68. //Set ACLS, create directory if it doesnt already exist
  69. if( FAILED(CreateDirectoryAndSetACLs(g_szWUDir, TRUE)))
  70. {
  71. goto done;
  72. }
  73. //We shouldnt care if we couldnt set attributes
  74. SetFileAttributes(g_szWUDir, FILE_ATTRIBUTE_HIDDEN | GetFileAttributes(g_szWUDir));
  75. }
  76. //Append the backslash
  77. if(FAILED(StringCchCatEx(g_szWUDir, ARRAYSIZE(g_szWUDir), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)))
  78. {
  79. goto done;
  80. }
  81. fRet = TRUE;
  82. done:
  83. if(!fRet)
  84. {
  85. g_szWUDir[0] = _T('\0');
  86. }
  87. else
  88. {
  89. fWUDirectoryExists = TRUE;
  90. }
  91. return fRet;
  92. }
  93. //this function delete all the files and subdirectories under lpszDir
  94. int DelDir(LPCTSTR lpszDir)
  95. {
  96. TCHAR szFilePattern[MAX_PATH], szFileName[MAX_PATH];
  97. HANDLE hFind;
  98. WIN32_FIND_DATA FindFileData;
  99. if ( NULL == lpszDir ||
  100. FAILED(StringCchCopyEx(szFilePattern, ARRAYSIZE(szFilePattern), lpszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  101. FAILED(StringCchCatEx(szFilePattern, ARRAYSIZE(szFilePattern), _T("\\*.*"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  102. INVALID_HANDLE_VALUE == (hFind = FindFirstFile(szFilePattern, &FindFileData)))
  103. {
  104. return 0;
  105. }
  106. FindNextFile(hFind, &FindFileData); //skip "." and ".."
  107. while(FindNextFile(hFind, &FindFileData))
  108. {
  109. if ( FAILED(StringCchCopyEx(szFileName, ARRAYSIZE(szFileName), lpszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  110. FAILED(StringCchCatEx(szFileName, ARRAYSIZE(szFileName), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  111. FAILED(StringCchCatEx(szFileName, ARRAYSIZE(szFileName), FindFileData.cFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)) )
  112. {
  113. FindClose(hFind);
  114. return 0;
  115. }
  116. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  117. {
  118. DelDir(szFileName);
  119. RemoveDirectory(szFileName);
  120. }
  121. else
  122. {
  123. DeleteFile(szFileName);
  124. }
  125. }
  126. FindClose(hFind);
  127. return 1;
  128. }
  129. ////////////////////////////////////////////////////////////////////////
  130. // Delete file using regular expression (e.g. *, ? etc)
  131. // tszDir : the directory where file resides. It ends with '\'
  132. // tszFilePattern: file(s) expressed in regular expression or plain format
  133. /////////////////////////////////////////////////////////////////////////
  134. int RegExpDelFile(LPCTSTR tszDir, LPCTSTR tszFilePattern)
  135. {
  136. WIN32_FIND_DATA fd;
  137. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  138. BOOL fMoreFiles = FALSE;
  139. TCHAR tszFileName[MAX_PATH+1];
  140. INT nRet = 1;
  141. if (FAILED(StringCchCopyEx(tszFileName, ARRAYSIZE(tszFileName), tszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  142. FAILED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), tszFilePattern, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  143. {
  144. nRet = 0;
  145. goto done;
  146. }
  147. hFindFile = FindFirstFile(tszFileName, &fd);
  148. if (INVALID_HANDLE_VALUE == hFindFile)
  149. {
  150. // DEBUGMSG("RegExpDelFile() no more files found");
  151. nRet = 0;
  152. goto done;
  153. }
  154. do
  155. {
  156. if (SUCCEEDED(StringCchCopyEx(tszFileName, ARRAYSIZE(tszFileName), tszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
  157. SUCCEEDED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
  158. SUCCEEDED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), fd.cFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  159. {
  160. // DEBUGMSG("RegExpDelFile() Deleting file %S", tszFileName);
  161. DeleteFile(tszFileName);
  162. }
  163. else
  164. {
  165. // DEBUGMSG("RegExpDelFile() failed to construct file name to delete");
  166. nRet = 0;
  167. }
  168. }
  169. while (fMoreFiles = FindNextFile(hFindFile, &fd));
  170. done:
  171. if (INVALID_HANDLE_VALUE != hFindFile)
  172. {
  173. FindClose(hFindFile);
  174. }
  175. return nRet;
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. //
  179. // Function CreateDownloadDir()
  180. // Creates the download directory
  181. //
  182. // Input: a string points to the directory to create
  183. // Output: None
  184. // Return: HRESULT to tell the result
  185. // Remarks: If the directory already exists, takes no action
  186. //
  187. /////////////////////////////////////////////////////////////////////////////
  188. HRESULT CreateDownloadDir(LPCTSTR lpszDir)
  189. {
  190. // USES_CONVERSION;
  191. DWORD dwRet = 0/*, attr*/;
  192. HRESULT hRet = E_FAIL;
  193. if (lpszDir == NULL || lpszDir[0] == EOS)
  194. {
  195. return E_INVALIDARG;
  196. }
  197. if (CreateDirectory(lpszDir, NULL))
  198. {
  199. if (!SetFileAttributes(lpszDir, FILE_ATTRIBUTE_HIDDEN))
  200. {
  201. dwRet = GetLastError();
  202. DEBUGMSG("CreateDownloadDir() failed to set hidden attribute to %S (%#lx).", lpszDir, dwRet);
  203. hRet = S_FALSE; // it's okay to use this dir.
  204. }
  205. else
  206. hRet = S_OK;
  207. }
  208. else
  209. {
  210. dwRet = GetLastError();
  211. if (dwRet != ERROR_ALREADY_EXISTS)
  212. {
  213. DEBUGMSG("CreateDownloadDir() failed to create directory %S (%#lx).", lpszDir, dwRet);
  214. hRet = HRESULT_FROM_WIN32(dwRet);
  215. }
  216. // ERROR_ALREADY_EXISTS is acceptable
  217. else
  218. hRet = S_OK;
  219. }
  220. return (hRet);
  221. }
  222. inline BOOL EnsureDirExists(LPCTSTR lpszDir)
  223. {
  224. BOOL fIsDir = FALSE;
  225. BOOL fRet = FALSE;
  226. if (fFileExists(lpszDir, &fIsDir))
  227. {
  228. if (!fIsDir)
  229. {
  230. DEBUGMSG("WARNING: directory squatting. File with same name %S exists", lpszDir);
  231. DeleteFile(lpszDir);
  232. }
  233. else
  234. {
  235. // DEBUGMSG("Direcotry %S exists, no need to create again", lpszDir);
  236. return TRUE;
  237. }
  238. }
  239. if (!(fRet = CreateNestedDirectory(lpszDir)))
  240. {
  241. DEBUGMSG("Fail to createnesteddirectory with error %d", GetLastError());
  242. }
  243. // DEBUGMSG(" Create directory %S %s", lpszDir, fRet ? "succeeded": "failed");
  244. return fRet;
  245. }
  246. /////////////////////////////////////////////////////////////////////////////
  247. //
  248. // Function GetDownloadPath()
  249. // Gets the download directory path
  250. // Input: a buffer to store the directory created and size of the buffer in TCHARs
  251. // Output: None
  252. // Return: HRESULT to tell the result
  253. //
  254. /////////////////////////////////////////////////////////////////////////////
  255. HRESULT GetDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
  256. {
  257. UINT nSize;
  258. TCHAR szDir[MAX_PATH];
  259. HRESULT hr;
  260. if (lpszDir == NULL)
  261. {
  262. return (E_INVALIDARG);
  263. }
  264. AUASSERT(_T('\0') != g_szWUDir[0]);
  265. if (FAILED(hr = StringCchCopyEx(szDir, ARRAYSIZE(szDir), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  266. {
  267. DEBUGMSG("GetDownloadPath() failed to get WinUpd directory");
  268. return hr;
  269. }
  270. if (FAILED(hr = PathCchAppend(szDir, ARRAYSIZE(szDir), C_DOWNLD_DIR)))
  271. {
  272. DEBUGMSG("GetDownloadPath() found input buffer too small.");
  273. return (hr);
  274. }
  275. if (FAILED(hr = StringCchCopyEx(lpszDir, dwCchSize, szDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  276. {
  277. DEBUGMSG("GetDownloadPath() call to StringCchCopyEx() failed.");
  278. return hr;
  279. }
  280. return EnsureDirExists(lpszDir) ? S_OK : E_FAIL;
  281. }
  282. HRESULT GetDownloadPathSubDir(LPTSTR lpszDir, DWORD dwCchSize, LPCTSTR tszSubDir)
  283. {
  284. HRESULT hr;
  285. if (FAILED(hr = GetDownloadPath(lpszDir, dwCchSize)))
  286. {
  287. DEBUGMSG("GetDownloadPathSubDir() fail to get download path");
  288. return hr;
  289. }
  290. if (FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  291. FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszSubDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  292. {
  293. DEBUGMSG("GetDownloadPathSubDir() failed to construct download path subdir with error %#lx.", hr);
  294. return hr;
  295. }
  296. return EnsureDirExists(lpszDir) ? S_OK : E_FAIL;
  297. }
  298. ///////////////////////////////////////////////////////////////
  299. // get the path to download software update bits
  300. // lpszDir : IN buffer to store the path and its size in TCHARs
  301. // return : S_OK if success
  302. // : E_INVALIDARG if buffer too small
  303. // : E_FAIL if other error
  304. //////////////////////////////////////////////////////////////
  305. HRESULT GetCabsDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
  306. {
  307. return GetDownloadPathSubDir(lpszDir, dwCchSize, CABS_DIR);
  308. }
  309. ///////////////////////////////////////////////////////////////
  310. // get the path to download UI specific data, like description and rtf
  311. // lpszDir : IN buffer to store the path and its size in TCHARs
  312. // return : S_OK if success
  313. //////////////////////////////////////////////////////////////
  314. HRESULT GetUISpecificDownloadPath(LPTSTR lpszDir, DWORD dwCchSize, LANGID langid, LPCTSTR tszSubDir)
  315. {
  316. HRESULT hr ;
  317. if (FAILED(hr = GetDownloadPath(lpszDir, dwCchSize)))
  318. {
  319. DEBUGMSG("GetUISpecificDownloadPath() fail to get download path");
  320. return hr;
  321. }
  322. TCHAR tszLangId[10];
  323. if (FAILED(StringCchPrintfEx(tszLangId, ARRAYSIZE(tszLangId), NULL, NULL, MISTSAFE_STRING_FLAGS, _T("%04x"), langid)))
  324. {
  325. return E_INVALIDARG;
  326. }
  327. if (FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  328. FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszSubDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  329. FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  330. FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszLangId, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  331. {
  332. DEBUGMSG("GetUISpecificDownloadPath() failed to construct ui specific download path with error %#lx.", hr);
  333. return hr;
  334. }
  335. return EnsureDirExists(lpszDir)? S_OK : E_FAIL;
  336. }
  337. ///////////////////////////////////////////////////////////////
  338. // get the rtf download path for a language
  339. // lpszDir : IN buffer to store the path and its size in TCHARs
  340. // return: S_OK if success
  341. // : E_INVALIDARG if buffer too small
  342. // : E_FAIL if other error
  343. //////////////////////////////////////////////////////////////
  344. HRESULT GetRTFDownloadPath(LPTSTR lpszDir, DWORD dwCchSize, LANGID langid)
  345. {
  346. return GetUISpecificDownloadPath(lpszDir, dwCchSize, langid, RTF_DIR);
  347. }
  348. /////////////////////////////////////////////////////////////////
  349. // get language independent RTF directory
  350. /////////////////////////////////////////////////////////////////
  351. HRESULT GetRTFDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
  352. {
  353. return GetDownloadPathSubDir(lpszDir, dwCchSize, RTF_DIR);
  354. }
  355. /////////////////////////////////////////////////////////////////////////////
  356. //
  357. // Function MakeTempDownloadDir()
  358. // Insures that a local temporary directory exists for downloads
  359. //
  360. // Input: pstrTarget - [out] path to temp dir and its size in TCHARs
  361. // Output: Makes a new directory if needed
  362. // Return: HRESULT
  363. /////////////////////////////////////////////////////////////////////////////
  364. HRESULT MakeTempDownloadDir(LPTSTR pszTarget, DWORD dwCchSize)
  365. {
  366. HRESULT hr;
  367. if (FAILED(hr = GetDownloadPath(pszTarget, dwCchSize)) ||
  368. // Make sure it exists
  369. FAILED(hr = CreateDownloadDir(pszTarget)))
  370. return hr;
  371. return NOERROR;
  372. }
  373. HRESULT GetRTFLocalFileName(BSTR bstrRTFPath, LPTSTR lpszFileName, DWORD dwCchSize, LANGID langid)
  374. {
  375. HRESULT hr ;
  376. hr = GetRTFDownloadPath(lpszFileName, dwCchSize, langid);
  377. if (SUCCEEDED(hr))
  378. {
  379. hr = PathCchAppend(lpszFileName, dwCchSize, PathFindFileName(W2T(bstrRTFPath)));
  380. }
  381. return hr;
  382. }