426 lines
12 KiB
C++
426 lines
12 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|