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.
1006 lines
34 KiB
1006 lines
34 KiB
|
|
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
RepositoryPackager.CPP
|
|
|
|
Abstract:
|
|
|
|
Recursively packages the contents of the repository directory into a single file,
|
|
and unpackages it.
|
|
|
|
History:
|
|
|
|
paulall 07-26-00 Created.
|
|
a-shawnb 07-27-00 Finished.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemcli.h>
|
|
#include "RepositoryPackager.h"
|
|
#include <arrtempl.h> // for CReleaseMe
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <cstring>
|
|
#include "a51tools.h"
|
|
//#include <autoptr.h>
|
|
|
|
wchar_t * CRepositoryPackager::backupFiles_[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"};
|
|
wchar_t * CRepositoryPackager::repDirectory_ = L"FS";
|
|
|
|
int __cdecl _adap_wbem_wcsicmp(const unsigned short * a,const unsigned short * b)
|
|
{
|
|
return wbem_wcsicmp(a,b);
|
|
}
|
|
|
|
bool CRepositoryPackager::needBackup(const wchar_t * fileName) const
|
|
{
|
|
const int maxSize = sizeof(backupFiles_)/sizeof(backupFiles_[0]);
|
|
return (std::find_if(&backupFiles_[0], &backupFiles_[maxSize], std::not1(std::bind1st(std::ptr_fun(_adap_wbem_wcsicmp),fileName))) != backupFiles_+maxSize);
|
|
};
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageRepository
|
|
*
|
|
* Description:
|
|
* Iterates deeply through the repository directly and packages it up
|
|
* into the given file specified by the given parameter.
|
|
* Repository directory is the one retrieved from the registry.
|
|
*
|
|
* Parameters:
|
|
* wszFilename: Filename we package everything up into
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageRepository(const wchar_t *wszFilename)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
CFileName wszRepositoryDirectory;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
int lBackupFileNameLen = 0;
|
|
bool bBackupFileExists = false;
|
|
|
|
CFileName wszBackupFileName;
|
|
if ((wszBackupFileName == NULL) || (wszRepositoryDirectory == NULL))
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
//Get the root directory of the repository
|
|
if (SUCCEEDED(hres))
|
|
hres = GetRepositoryDirectory(wszRepositoryDirectory);
|
|
|
|
//Create a new file to package contents up to...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
if ((GetLastError() != ERROR_FILE_EXISTS) && (GetLastError() != ERROR_ALREADY_EXISTS ))
|
|
{
|
|
hres = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
//We need to back up the existing file in case we fail and need to restore it
|
|
StringCchCopyW(wszBackupFileName, wszBackupFileName.Length(), wszFilename);
|
|
StringCchCatW(wszBackupFileName, wszBackupFileName.Length(), L".");
|
|
lBackupFileNameLen = wcslen(wszBackupFileName);
|
|
|
|
for (int i = 0; i != 100; i++)
|
|
{
|
|
_itow(i, wszBackupFileName+lBackupFileNameLen, 10);
|
|
if (MoveFileW(wszFilename, wszBackupFileName))
|
|
{
|
|
//We
|
|
Succeeded!
|
|
bBackupFileExists = true;
|
|
|
|
//Now we need to open the file again!
|
|
hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
hres = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//If we failed with all them we may as well just give up here!
|
|
if (!bBackupFileExists)
|
|
hres = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Write the package header...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = PackageHeader(hFile);
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = PackageAllFiles(hFile, wszRepositoryDirectory);
|
|
}
|
|
|
|
//Write the end of package marker
|
|
if (SUCCEEDED(hres))
|
|
hres = PackageTrailer(hFile);
|
|
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFile);
|
|
|
|
//If things failed we should delete the file...
|
|
if (FAILED(hres))
|
|
DeleteFileW(wszFilename);
|
|
|
|
//If there is a backup file, rename it back in failure case
|
|
//or delete in other cases
|
|
if (FAILED(hres) && bBackupFileExists && wszBackupFileName)
|
|
MoveFileW(wszBackupFileName, wszFilename);
|
|
else if (bBackupFileExists && wszBackupFileName)
|
|
DeleteFileW(wszBackupFileName);
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::UnpackageRepository
|
|
*
|
|
* Description:
|
|
* Given the filename of a packaged up repository we unpack everything
|
|
* into the repository directory specified in the registry. The
|
|
* directory should have no files in it before doing this.
|
|
*
|
|
* Parameters:
|
|
* wszFilename: Filename we unpackage everything from
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::UnpackageRepository(const wchar_t *wszFilename)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
wchar_t wszRepositoryDirectory[MAX_PATH+1];
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
|
|
//Get the root directory of the repository
|
|
hres = GetRepositoryDirectory(wszRepositoryDirectory);
|
|
|
|
//open the file for unpacking...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hFile = CreateFileW(wszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
hres = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//unpack the package header...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = UnPackageHeader(hFile);
|
|
}
|
|
|
|
//unpack the file...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = UnPackageContentsOfDirectory(hFile, wszRepositoryDirectory);
|
|
}
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFile);
|
|
|
|
//If things failed we should delete the partially unpacked repository...
|
|
if (FAILED(hres))
|
|
DeleteRepository();
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::DeleteRepository
|
|
*
|
|
* Description:
|
|
* Delete all files and directories under the repository directory.
|
|
* The repository directory location is retrieved from the registry.
|
|
*
|
|
* Parameters:
|
|
* <none>
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::DeleteRepository()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
wchar_t *wszRepositoryOrg = new wchar_t[MAX_PATH+1];
|
|
CVectorDeleteMe<wchar_t> vdm1(wszRepositoryOrg);
|
|
|
|
if (!wszRepositoryOrg)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = GetRepositoryDirectory(wszRepositoryOrg);
|
|
|
|
//MOVE EACH OF THE FILES, ONE BY ONE
|
|
for (int i = 0; SUCCEEDED(hr) && (i != 6); i++)
|
|
{
|
|
static wchar_t *filename[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"};
|
|
CFileName wszDestinationFile;
|
|
if (!wszDestinationFile)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
StringCchCopyW(wszDestinationFile, wszDestinationFile.Length(), wszRepositoryOrg);
|
|
|
|
if (i != 0)
|
|
{
|
|
StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), L"\\fs");
|
|
}
|
|
StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), filename[i]);
|
|
|
|
if (!DeleteFileW(wszDestinationFile))
|
|
{
|
|
if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND))
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CRepositoryPackager::PackageAllFiles(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
|
|
{
|
|
//
|
|
// internally PackageFile check for existence
|
|
// this is a matter only when $WinMgMt.CFG is packeged, since it cannot be there
|
|
// if PackeageFile is called from within the FindFirst/FindNext loop, then the
|
|
// existence of the file is ensured by the context
|
|
//
|
|
HRESULT hres = PackageFile(hFile, wszRepositoryDirectory, backupFiles_[0]);
|
|
if (FAILED(hres))
|
|
return hres;
|
|
|
|
hres = PackageDirectory(hFile, wszRepositoryDirectory, repDirectory_);
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageContentsOfDirectory
|
|
*
|
|
* Description:
|
|
* Given a directory, iterates through all files and directories and
|
|
* calls into the function to package it into the file specified by the
|
|
* file handle passed to the method.
|
|
*
|
|
* Parameters:
|
|
* hFile: Handle to the destination file.
|
|
* wszRepositoryDirectory: Directory to process
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
|
|
WIN32_FIND_DATAW findFileData;
|
|
HANDLE hff = INVALID_HANDLE_VALUE;
|
|
|
|
//create file search pattern...
|
|
CFileName wszSearchPattern;
|
|
if (wszSearchPattern == NULL)
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory);
|
|
StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*");
|
|
}
|
|
|
|
//Start the file iteration in this directory...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hff = FindFirstFileW(wszSearchPattern, &findFileData);
|
|
if (hff == INVALID_HANDLE_VALUE)
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
do
|
|
{
|
|
//If we have a filename of '.' or '..' we ignore it...
|
|
if ((wcscmp(findFileData.cFileName, L".") == 0) ||
|
|
(wcscmp(findFileData.cFileName, L"..") == 0))
|
|
{
|
|
//Do nothing with these...
|
|
}
|
|
else
|
|
{
|
|
//This is a file, so we need to deal with that...
|
|
hres = PackageFile(hFile, wszRepositoryDirectory, findFileData.cFileName);
|
|
if (FAILED(hres))
|
|
break;
|
|
}
|
|
|
|
} while (FindNextFileW(hff, &findFileData));
|
|
}
|
|
|
|
if (hff != INVALID_HANDLE_VALUE)
|
|
FindClose(hff);
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::GetRepositoryDirectory
|
|
*
|
|
* Description:
|
|
* Retrieves the location of the repository directory from the registry.
|
|
*
|
|
* Parameters:
|
|
* wszRepositoryDirectory: Array to store location in.
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1])
|
|
{
|
|
HKEY hKey;
|
|
long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
|
|
0, KEY_READ, &hKey);
|
|
if(lRes)
|
|
return WBEM_E_FAILED;
|
|
|
|
wchar_t wszTmp[MAX_PATH + 1];
|
|
DWORD dwLen = (MAX_PATH + 1)*sizeof(wchar_t);
|
|
lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL,
|
|
(LPBYTE)wszTmp, &dwLen);
|
|
RegCloseKey(hKey);
|
|
if(lRes)
|
|
return WBEM_E_FAILED;
|
|
|
|
if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0)
|
|
return WBEM_E_FAILED;
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageHeader
|
|
*
|
|
* Description:
|
|
* Stores the header package in the given file. This is a footprint
|
|
* so we can recognise if this really is one of our files when
|
|
* we try to decode it. Also it allows us to version it.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to store header in.
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageHeader(HANDLE hFile)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
PACKAGE_HEADER header;
|
|
StringCchCopyA(header.szSignature, 10, "FS PKG1.1"); //NOTE! MAXIMUM OF 10 CHARACTERS (INCLUDING TERMINATOR!)
|
|
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
|
|
hres = WBEM_E_FAILED;
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageDirectory
|
|
*
|
|
* Description:
|
|
* This is the code which processes a directory. It stores the namespace
|
|
* header and footer marker in the file, and also iterates through
|
|
* all files and directories in that directory.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to store directory information in.
|
|
* wszParentDirectory: Full path of parent directory
|
|
* eszSubDirectory: Name of sub-directory to process
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
|
|
{
|
|
PACKAGE_SPACER_NAMESPACE header;
|
|
header.dwSpacerType = PACKAGE_TYPE_NAMESPACE_START;
|
|
StringCchCopyW(header.wszNamespaceName, MAX_PATH+1, wszSubDirectory);
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
//Get full path of new directory...
|
|
CFileName wszFullDirectoryName;
|
|
if (wszFullDirectoryName == NULL) hres = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory);
|
|
}
|
|
|
|
//Package the contents of that directory...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = PackageContentsOfDirectory(hFile, wszFullDirectoryName);
|
|
}
|
|
|
|
//Now need to write the end of package marker...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
PACKAGE_SPACER header2;
|
|
header2.dwSpacerType = PACKAGE_TYPE_NAMESPACE_END;
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, &header2, sizeof(header2), &dwSize, NULL) == 0) || (dwSize != sizeof(header2)))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageFile
|
|
*
|
|
* Description:
|
|
* This is the code which processes a file. It stores the file header
|
|
* and the contents of the file into the destination file whose handle
|
|
* is passed in. The file directory and name is passed in.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to store directory information in.
|
|
* wszParentDirectory: Full path of parent directory
|
|
* wszFilename: Name of file to process
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageFile(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszFilename)
|
|
{
|
|
if (needBackup(wszFilename) == false) return WBEM_S_NO_ERROR;
|
|
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
|
|
PACKAGE_SPACER_FILE header;
|
|
header.dwSpacerType = PACKAGE_TYPE_FILE;
|
|
StringCchCopyW(header.wszFileName, MAX_PATH+1, wszFilename);
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA fileAttribs;
|
|
CFileName wszFullFileName;
|
|
if (wszFullFileName == NULL)
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory);
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), wszFilename);
|
|
|
|
if (GetFileAttributesExW(wszFullFileName, GetFileExInfoStandard, &fileAttribs) == 0)
|
|
{
|
|
if (ERROR_FILE_NOT_FOUND == GetLastError())
|
|
return WBEM_S_NO_ERROR;
|
|
else
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
header.dwFileSize = fileAttribs.nFileSizeLow;
|
|
}
|
|
}
|
|
|
|
//Write header...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
//Now need to write actual contents of file to current one... but only if the file is not 0 bytes long...
|
|
if (SUCCEEDED(hres) && (header.dwFileSize != 0))
|
|
{
|
|
HANDLE hFromFile = CreateFileW(wszFullFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFromFile == INVALID_HANDLE_VALUE)
|
|
hres = WBEM_E_FAILED;
|
|
|
|
BYTE *pFileBlob = NULL;
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
pFileBlob = new BYTE[header.dwFileSize];
|
|
if (pFileBlob == NULL)
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(hFromFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
delete pFileBlob;
|
|
|
|
if (hFromFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFromFile);
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageTrailer
|
|
*
|
|
* Description:
|
|
* Writes the end of file marker to the file.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to store directory information in.
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageTrailer(HANDLE hFile)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
PACKAGE_SPACER trailer;
|
|
trailer.dwSpacerType = PACKAGE_TYPE_END_OF_FILE;
|
|
|
|
DWORD dwSize = 0;
|
|
if ((WriteFile(hFile, &trailer, sizeof(trailer), &dwSize, NULL) == 0) || (dwSize != sizeof(trailer)))
|
|
hres = WBEM_E_FAILED;
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::UnPackageHeader
|
|
*
|
|
* Description:
|
|
* Unpacks the header package in the given file. This allows us to recognise
|
|
* if this really is one of our files. Also it allows us to version it.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to unpack header from.
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::UnPackageHeader(HANDLE hFile)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
PACKAGE_HEADER header;
|
|
|
|
DWORD dwSize = 0;
|
|
if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
else if (strncmp(header.szSignature,"FS PKG1.1", 9) != 0)
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::UnPackageContentsOfDirectory
|
|
*
|
|
* Description:
|
|
* Unpack the contents of a namespace/directory.
|
|
* If a subdirectory is encountered, then it calls UnPackageDirectory to handle it.
|
|
* If a file is encountered, then it calls UnPackageFile to handle it.
|
|
* If no errors occur, then it will enventually encounter the end of the namespace,
|
|
* which will terminate the loop and return control to the calling function.
|
|
*
|
|
* Parameters:
|
|
* hFile: Handle to the file to unpack from
|
|
* wszRepositoryDirectory: Directory to write to.
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::UnPackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
PACKAGE_SPACER header;
|
|
DWORD dwSize;
|
|
|
|
while (hres == WBEM_S_NO_ERROR)
|
|
{
|
|
// this loop will be exited when we either
|
|
// - successfully process a complete directory/namespace
|
|
// - encounter an error
|
|
|
|
dwSize = 0;
|
|
if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_START)
|
|
{
|
|
hres = UnPackageDirectory(hFile, wszRepositoryDirectory);
|
|
}
|
|
else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_END)
|
|
{
|
|
// done with this directory
|
|
break;
|
|
}
|
|
else if (header.dwSpacerType == PACKAGE_TYPE_FILE)
|
|
{
|
|
hres = UnPackageFile(hFile, wszRepositoryDirectory);
|
|
}
|
|
else if (header.dwSpacerType == PACKAGE_TYPE_END_OF_FILE)
|
|
{
|
|
// done unpacking
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::UnPackageDirectory
|
|
*
|
|
* Description:
|
|
* Unpack the start of a namespace, then call UnPackageContentsOfDirectory
|
|
* to handle everything within it.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to unpack directory information from.
|
|
* wszParentDirectory: Full path of parent directory
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::UnPackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory)
|
|
{
|
|
PACKAGE_SPACER_NAMESPACE header;
|
|
|
|
// read namespace/directory name
|
|
DWORD dwSize = 0;
|
|
DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER);
|
|
if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
//Get full path of new directory...
|
|
CFileName wszFullDirectoryName;
|
|
if (NULL == (wchar_t *)wszFullDirectoryName) return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), header.wszNamespaceName);
|
|
|
|
// create directory
|
|
if (!CreateDirectoryW(wszFullDirectoryName, NULL))
|
|
{
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS) return WBEM_E_FAILED;
|
|
}
|
|
|
|
// UnPackage the contents into the new directory...
|
|
return UnPackageContentsOfDirectory(hFile, wszFullDirectoryName);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::UnPackageFile
|
|
*
|
|
* Description:
|
|
* Unpack a file.
|
|
*
|
|
* Parameters:
|
|
* hFile: File handle to unpack file information from.
|
|
* wszParentDirectory: Full path of parent directory
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::UnPackageFile(HANDLE hFile, const wchar_t *wszParentDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
PACKAGE_SPACER_FILE header;
|
|
|
|
// read file name and size
|
|
DWORD dwSize = 0;
|
|
DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER);
|
|
if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead))
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
//Get full path of new file...
|
|
CFileName wszFullFileName;
|
|
if (NULL == (wchar_t *)wszFullFileName) hres = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory);
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), header.wszFileName);
|
|
}
|
|
|
|
// create the file
|
|
HANDLE hNewFile = INVALID_HANDLE_VALUE;
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hNewFile = CreateFileW(wszFullFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hNewFile == INVALID_HANDLE_VALUE)
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
// read file blob and write to file if size is greater than zero
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
if (header.dwFileSize > 0)
|
|
{
|
|
BYTE* pFileBlob = new BYTE[header.dwFileSize];
|
|
if (pFileBlob == NULL)
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
dwSize = 0;
|
|
if ((ReadFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
// write file
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
dwSize = 0;
|
|
if ((WriteFile(hNewFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
|
|
if (pFileBlob)
|
|
delete pFileBlob;
|
|
}
|
|
}
|
|
|
|
if (hNewFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hNewFile);
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::DeleteContentsOfDirectory
|
|
*
|
|
* Description:
|
|
* Given a directory, iterates through all files and directories and
|
|
* calls into the function to delete it.
|
|
*
|
|
* Parameters:
|
|
* wszRepositoryDirectory: Directory to process
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::DeleteContentsOfDirectory(const wchar_t *wszRepositoryDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
|
|
CFileName wszFullFileName;
|
|
if (wszFullFileName == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
WIN32_FIND_DATAW findFileData;
|
|
HANDLE hff = INVALID_HANDLE_VALUE;
|
|
|
|
//create file search pattern...
|
|
CFileName wszSearchPattern;
|
|
if (wszSearchPattern == NULL)
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
{
|
|
StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory);
|
|
StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*");
|
|
}
|
|
|
|
//Start the file iteration in this directory...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hff = FindFirstFileW(wszSearchPattern, &findFileData);
|
|
if (hff == INVALID_HANDLE_VALUE)
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
do
|
|
{
|
|
//If we have a filename of '.' or '..' we ignore it...
|
|
if ((wcscmp(findFileData.cFileName, L".") == 0) ||
|
|
(wcscmp(findFileData.cFileName, L"..") == 0))
|
|
{
|
|
//Do nothing with these...
|
|
}
|
|
else if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
//This is a directory, so we need to deal with that...
|
|
hres = PackageDeleteDirectory(wszRepositoryDirectory, findFileData.cFileName);
|
|
if (FAILED(hres))
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//This is a file, so we need to deal with that...
|
|
StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszRepositoryDirectory);
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
|
|
StringCchCatW(wszFullFileName, wszFullFileName.Length(), findFileData.cFileName);
|
|
if (!DeleteFileW(wszFullFileName))
|
|
{
|
|
hres = WBEM_E_FAILED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (FindNextFileW(hff, &findFileData));
|
|
}
|
|
|
|
if (hff != INVALID_HANDLE_VALUE)
|
|
FindClose(hff);
|
|
|
|
return hres;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CRepositoryPackager::PackageDeleteDirectory
|
|
*
|
|
* Description:
|
|
* This is the code which processes a directory. It iterates through
|
|
* all files and directories in that directory.
|
|
*
|
|
* Parameters:
|
|
* wszParentDirectory: Full path of parent directory
|
|
* eszSubDirectory: Name of sub-directory to process
|
|
*
|
|
* Return:
|
|
* HRESULT: WBEM_S_NO_ERROR If successful
|
|
* WBEM_E_OUT_OF_MEMORY If out of memory
|
|
* WBEM_E_FAILED If anything else failed
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
HRESULT CRepositoryPackager::PackageDeleteDirectory(const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory)
|
|
{
|
|
HRESULT hres = WBEM_S_NO_ERROR;
|
|
|
|
//Get full path of new directory...
|
|
CFileName wszFullDirectoryName;
|
|
if (wszFullDirectoryName == NULL) return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
|
|
StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory);
|
|
}
|
|
|
|
//Package the contents of that directory...
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = DeleteContentsOfDirectory(wszFullDirectoryName);
|
|
}
|
|
|
|
// now that the directory is empty, remove it
|
|
if (!RemoveDirectoryW(wszFullDirectoryName))
|
|
hres = WBEM_E_FAILED;
|
|
|
|
return hres;
}
|