windows-nt/Source/XPSP1/NT/enduser/windows.com/wuau/wuaulib/audirectory.cpp

426 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: wudirectory.cpp
// Desc: This is the definition file that implements function(s)
// related to find out where to get the Critical Fix cab file.
//
//--------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
TCHAR g_szWUDir[MAX_PATH+1] = _T("\0"); //Path to windows update directory
const TCHAR CABS_DIR[] = _T("cabs");
const TCHAR RTF_DIR[] = _T("RTF");
const TCHAR EULA_DIR[] = _T("EULA");
const TCHAR DETAILS_DIR[] = _T("Details");
const TCHAR C_DOWNLD_DIR[] = _T("wuaudnld.tmp");
BOOL AUDelFileOrDir(LPCTSTR szFileOrDir)
{
if (NULL == szFileOrDir)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
BOOL fIsDir = TRUE;
if (fFileExists(szFileOrDir, &fIsDir))
{
if (fIsDir)
{
if (DelDir(szFileOrDir))
{
return RemoveDirectory(szFileOrDir);
}
return FALSE;
}
else
{
return DeleteFile(szFileOrDir);
}
}
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
////////////////////////////////////////////////////////////////////////
// Create the WU directory if it doesnt already exist
// return FALSE if failed
/////////////////////////////////////////////////////////////////////////
BOOL CreateWUDirectory(BOOL fGetPathOnly)
{
BOOL fRet = FALSE;
static BOOL fWUDirectoryExists = FALSE;
// WindowsUpdate Directory already exists
if (fWUDirectoryExists)
{
fRet = TRUE;
goto done;
}
//Get the path to the windows update directory
if( !GetWUDirectory(g_szWUDir, ARRAYSIZE(g_szWUDir)))
{
goto done;
}
//If we need to set the acls to the directory
if(!fGetPathOnly)
{
//Set ACLS, create directory if it doesnt already exist
if( FAILED(CreateDirectoryAndSetACLs(g_szWUDir, TRUE)))
{
goto done;
}
//We shouldnt care if we couldnt set attributes
SetFileAttributes(g_szWUDir, FILE_ATTRIBUTE_HIDDEN | GetFileAttributes(g_szWUDir));
}
//Append the backslash
if(FAILED(StringCchCatEx(g_szWUDir, ARRAYSIZE(g_szWUDir), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
goto done;
}
fRet = TRUE;
done:
if(!fRet)
{
g_szWUDir[0] = _T('\0');
}
else
{
fWUDirectoryExists = TRUE;
}
return fRet;
}
//this function delete all the files and subdirectories under lpszDir
int DelDir(LPCTSTR lpszDir)
{
TCHAR szFilePattern[MAX_PATH], szFileName[MAX_PATH];
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
if ( NULL == lpszDir ||
FAILED(StringCchCopyEx(szFilePattern, ARRAYSIZE(szFilePattern), lpszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(szFilePattern, ARRAYSIZE(szFilePattern), _T("\\*.*"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
INVALID_HANDLE_VALUE == (hFind = FindFirstFile(szFilePattern, &FindFileData)))
{
return 0;
}
FindNextFile(hFind, &FindFileData); //skip "." and ".."
while(FindNextFile(hFind, &FindFileData))
{
if ( FAILED(StringCchCopyEx(szFileName, ARRAYSIZE(szFileName), lpszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(szFileName, ARRAYSIZE(szFileName), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(szFileName, ARRAYSIZE(szFileName), FindFileData.cFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)) )
{
FindClose(hFind);
return 0;
}
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
DelDir(szFileName);
RemoveDirectory(szFileName);
}
else
{
DeleteFile(szFileName);
}
}
FindClose(hFind);
return 1;
}
////////////////////////////////////////////////////////////////////////
// Delete file using regular expression (e.g. *, ? etc)
// tszDir : the directory where file resides. It ends with '\'
// tszFilePattern: file(s) expressed in regular expression or plain format
/////////////////////////////////////////////////////////////////////////
int RegExpDelFile(LPCTSTR tszDir, LPCTSTR tszFilePattern)
{
WIN32_FIND_DATA fd;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
BOOL fMoreFiles = FALSE;
TCHAR tszFileName[MAX_PATH+1];
INT nRet = 1;
if (FAILED(StringCchCopyEx(tszFileName, ARRAYSIZE(tszFileName), tszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), tszFilePattern, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
nRet = 0;
goto done;
}
hFindFile = FindFirstFile(tszFileName, &fd);
if (INVALID_HANDLE_VALUE == hFindFile)
{
// DEBUGMSG("RegExpDelFile() no more files found");
nRet = 0;
goto done;
}
do
{
if (SUCCEEDED(StringCchCopyEx(tszFileName, ARRAYSIZE(tszFileName), tszDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
SUCCEEDED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
SUCCEEDED(StringCchCatEx(tszFileName, ARRAYSIZE(tszFileName), fd.cFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
// DEBUGMSG("RegExpDelFile() Deleting file %S", tszFileName);
DeleteFile(tszFileName);
}
else
{
// DEBUGMSG("RegExpDelFile() failed to construct file name to delete");
nRet = 0;
}
}
while (fMoreFiles = FindNextFile(hFindFile, &fd));
done:
if (INVALID_HANDLE_VALUE != hFindFile)
{
FindClose(hFindFile);
}
return nRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// Function CreateDownloadDir()
// Creates the download directory
//
// Input: a string points to the directory to create
// Output: None
// Return: HRESULT to tell the result
// Remarks: If the directory already exists, takes no action
//
/////////////////////////////////////////////////////////////////////////////
HRESULT CreateDownloadDir(LPCTSTR lpszDir)
{
// USES_CONVERSION;
DWORD dwRet = 0/*, attr*/;
HRESULT hRet = E_FAIL;
if (lpszDir == NULL || lpszDir[0] == EOS)
{
return E_INVALIDARG;
}
if (CreateDirectory(lpszDir, NULL))
{
if (!SetFileAttributes(lpszDir, FILE_ATTRIBUTE_HIDDEN))
{
dwRet = GetLastError();
DEBUGMSG("CreateDownloadDir() failed to set hidden attribute to %S (%#lx).", lpszDir, dwRet);
hRet = S_FALSE; // it's okay to use this dir.
}
else
hRet = S_OK;
}
else
{
dwRet = GetLastError();
if (dwRet != ERROR_ALREADY_EXISTS)
{
DEBUGMSG("CreateDownloadDir() failed to create directory %S (%#lx).", lpszDir, dwRet);
hRet = HRESULT_FROM_WIN32(dwRet);
}
// ERROR_ALREADY_EXISTS is acceptable
else
hRet = S_OK;
}
return (hRet);
}
inline BOOL EnsureDirExists(LPCTSTR lpszDir)
{
BOOL fIsDir = FALSE;
BOOL fRet = FALSE;
if (fFileExists(lpszDir, &fIsDir))
{
if (!fIsDir)
{
DEBUGMSG("WARNING: directory squatting. File with same name %S exists", lpszDir);
DeleteFile(lpszDir);
}
else
{
// DEBUGMSG("Direcotry %S exists, no need to create again", lpszDir);
return TRUE;
}
}
if (!(fRet = CreateNestedDirectory(lpszDir)))
{
DEBUGMSG("Fail to createnesteddirectory with error %d", GetLastError());
}
// DEBUGMSG(" Create directory %S %s", lpszDir, fRet ? "succeeded": "failed");
return fRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// Function GetDownloadPath()
// Gets the download directory path
// Input: a buffer to store the directory created and size of the buffer in TCHARs
// Output: None
// Return: HRESULT to tell the result
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
{
UINT nSize;
TCHAR szDir[MAX_PATH];
HRESULT hr;
if (lpszDir == NULL)
{
return (E_INVALIDARG);
}
AUASSERT(_T('\0') != g_szWUDir[0]);
if (FAILED(hr = StringCchCopyEx(szDir, ARRAYSIZE(szDir), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
DEBUGMSG("GetDownloadPath() failed to get WinUpd directory");
return hr;
}
if (FAILED(hr = PathCchAppend(szDir, ARRAYSIZE(szDir), C_DOWNLD_DIR)))
{
DEBUGMSG("GetDownloadPath() found input buffer too small.");
return (hr);
}
if (FAILED(hr = StringCchCopyEx(lpszDir, dwCchSize, szDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
DEBUGMSG("GetDownloadPath() call to StringCchCopyEx() failed.");
return hr;
}
return EnsureDirExists(lpszDir) ? S_OK : E_FAIL;
}
HRESULT GetDownloadPathSubDir(LPTSTR lpszDir, DWORD dwCchSize, LPCTSTR tszSubDir)
{
HRESULT hr;
if (FAILED(hr = GetDownloadPath(lpszDir, dwCchSize)))
{
DEBUGMSG("GetDownloadPathSubDir() fail to get download path");
return hr;
}
if (FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszSubDir, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
DEBUGMSG("GetDownloadPathSubDir() failed to construct download path subdir with error %#lx.", hr);
return hr;
}
return EnsureDirExists(lpszDir) ? S_OK : E_FAIL;
}
///////////////////////////////////////////////////////////////
// get the path to download software update bits
// lpszDir : IN buffer to store the path and its size in TCHARs
// return : S_OK if success
// : E_INVALIDARG if buffer too small
// : E_FAIL if other error
//////////////////////////////////////////////////////////////
HRESULT GetCabsDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
{
return GetDownloadPathSubDir(lpszDir, dwCchSize, CABS_DIR);
}
///////////////////////////////////////////////////////////////
// get the path to download UI specific data, like description and rtf
// lpszDir : IN buffer to store the path and its size in TCHARs
// return : S_OK if success
//////////////////////////////////////////////////////////////
HRESULT GetUISpecificDownloadPath(LPTSTR lpszDir, DWORD dwCchSize, LANGID langid, LPCTSTR tszSubDir)
{
HRESULT hr ;
if (FAILED(hr = GetDownloadPath(lpszDir, dwCchSize)))
{
DEBUGMSG("GetUISpecificDownloadPath() fail to get download path");
return hr;
}
TCHAR tszLangId[10];
if (FAILED(StringCchPrintfEx(tszLangId, ARRAYSIZE(tszLangId), NULL, NULL, MISTSAFE_STRING_FLAGS, _T("%04x"), langid)))
{
return E_INVALIDARG;
}
if (FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszSubDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
FAILED(hr = StringCchCatEx(lpszDir, dwCchSize, tszLangId, NULL, NULL, MISTSAFE_STRING_FLAGS)))
{
DEBUGMSG("GetUISpecificDownloadPath() failed to construct ui specific download path with error %#lx.", hr);
return hr;
}
return EnsureDirExists(lpszDir)? S_OK : E_FAIL;
}
///////////////////////////////////////////////////////////////
// get the rtf download path for a language
// lpszDir : IN buffer to store the path and its size in TCHARs
// return: S_OK if success
// : E_INVALIDARG if buffer too small
// : E_FAIL if other error
//////////////////////////////////////////////////////////////
HRESULT GetRTFDownloadPath(LPTSTR lpszDir, DWORD dwCchSize, LANGID langid)
{
return GetUISpecificDownloadPath(lpszDir, dwCchSize, langid, RTF_DIR);
}
/////////////////////////////////////////////////////////////////
// get language independent RTF directory
/////////////////////////////////////////////////////////////////
HRESULT GetRTFDownloadPath(LPTSTR lpszDir, DWORD dwCchSize)
{
return GetDownloadPathSubDir(lpszDir, dwCchSize, RTF_DIR);
}
/////////////////////////////////////////////////////////////////////////////
//
// Function MakeTempDownloadDir()
// Insures that a local temporary directory exists for downloads
//
// Input: pstrTarget - [out] path to temp dir and its size in TCHARs
// Output: Makes a new directory if needed
// Return: HRESULT
/////////////////////////////////////////////////////////////////////////////
HRESULT MakeTempDownloadDir(LPTSTR pszTarget, DWORD dwCchSize)
{
HRESULT hr;
if (FAILED(hr = GetDownloadPath(pszTarget, dwCchSize)) ||
// Make sure it exists
FAILED(hr = CreateDownloadDir(pszTarget)))
return hr;
return NOERROR;
}
HRESULT GetRTFLocalFileName(BSTR bstrRTFPath, LPTSTR lpszFileName, DWORD dwCchSize, LANGID langid)
{
HRESULT hr ;
hr = GetRTFDownloadPath(lpszFileName, dwCchSize, langid);
if (SUCCEEDED(hr))
{
hr = PathCchAppend(lpszFileName, dwCchSize, PathFindFileName(W2T(bstrRTFPath)));
}
return hr;
}