windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/roswell/a51imp.cpp

623 lines
15 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
A51Imp.cpp
Abstract:
Imports an export file into the repository. This uses the export file format defined
in A51Exp.cpp.
History:
08-Dec-2000 paulall Created.
--*/
#include <windows.h>
#include <ql.h>
#include "A51Rep.h"
#include "A51Exp.h"
#include "A51Imp.h"
//extern CFileCache* g_FileCache;
extern CGlobals g_Glob;
/*=============================================================================
*
* A51Import::A51Import
*
*=============================================================================
*/
A51Import::A51Import()
: m_hFile(INVALID_HANDLE_VALUE),
m_bSkipMode(false)
{
}
/*=============================================================================
*
* A51Import::~A51Import
*
*=============================================================================
*/
A51Import::~A51Import()
{
}
/*=============================================================================
*
* A51Import::Import
*
*=============================================================================
*/
HRESULT A51Import::Import(const wchar_t *wszFilename, DWORD dwFlags, CRepository *pRepository)
{
HRESULT hRes = WBEM_S_NO_ERROR;
m_pRepository = pRepository;
//Open the import file for reading
m_hFile = CreateFileW(wszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (m_hFile == INVALID_HANDLE_VALUE)
hRes = WBEM_E_FAILED;
try
{
//Check the header is valid, in case we were given an invalid file format
if (SUCCEEDED(hRes))
hRes = ImportHeader();
//Retrieve the type of the next object to process
DWORD dwObjectType;
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
//While we are not at the end of the file, loop through the items
while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_FILE_END_TAG))
{
//Only namespace objects should reside at this level!
switch (dwObjectType)
{
case A51_EXPORT_NAMESPACE_TAG:
{
hRes = ImportNamespace();
break;
}
default:
{
hRes = WBEM_E_FAILED;
break;
}
}
//Get the next type of object
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
}
}
catch (...)
{
hRes = WBEM_E_CRITICAL_ERROR;
ERRORTRACE((LOG_WBEMCORE, "Critical error happened while re-importing the repository, error <0x%X>\n", hRes));
}
if (m_hFile)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
m_hFile = INVALID_HANDLE_VALUE;
return hRes;
}
/*=============================================================================
*
* A51Import::ImportHeader
*
* File Header Block:
* BYTE wszFileHeader[8] = A51_EXPORT_FILE_START_TAG ("a51exp1")
*
*=============================================================================
*/
HRESULT A51Import::ImportHeader()
{
HRESULT hRes = WBEM_S_NO_ERROR;
char *pszExpectedHeader = A51_EXPORT_FILE_START_TAG;
DWORD dwSize = sizeof(A51_EXPORT_FILE_START_TAG);
char *pszActualHeader = new char[dwSize];
CVectorDeleteMe<char> vdm1(pszActualHeader);
if (pszActualHeader == NULL)
{
hRes = WBEM_E_OUT_OF_MEMORY;
}
//Read header
if (SUCCEEDED(hRes) &&
((!ReadFile(m_hFile, pszActualHeader, dwSize, &dwSize, NULL)) ||
(dwSize != sizeof(A51_EXPORT_FILE_START_TAG))))
{
hRes = WBEM_E_FAILED;
}
//If last character is not a NULL terminator then it fails outright!
if (SUCCEEDED(hRes) && (pszActualHeader[sizeof(A51_EXPORT_FILE_START_TAG) - 1] != '\0'))
{
hRes = WBEM_E_FAILED;
}
//Do check to see if rest is the same....
if ((SUCCEEDED(hRes)) && (lstrcmpA(pszExpectedHeader, pszActualHeader) != 0))
{
hRes = WBEM_E_FAILED;
}
return hRes;
}
/*=============================================================================
*
* A51Import::ImportNamespace
*
* Namespace Block:
* DWORD dwObjectType = A51_EXPORT_NAMESPACE_TAG
* DWORD dwNamespaceNameSize
* BYTE wszNamespaceName[dwNamespaceNameSize] = Full namespace name
*
*=============================================================================
*/
HRESULT A51Import::ImportNamespace()
{
HRESULT hRes;
DWORD dwLength = 0;
wchar_t *wszNamespaceName = NULL;
//Retrieve the namespace name from the import file
hRes = ReadBufferWithLength(&dwLength, (void**) &wszNamespaceName);
CVectorDeleteMe<wchar_t> vdm1(wszNamespaceName);
//Create a namespace object for this namespace
CNamespaceHandle *pNs = NULL;
if (SUCCEEDED(hRes))
{
DEBUGTRACE((LOG_WBEMCORE, "Namespace import for namespace <%S>\n", wszNamespaceName));
pNs = new CNamespaceHandle(NULL, m_pRepository);
if (pNs == NULL)
hRes = WBEM_E_OUT_OF_MEMORY;
else
{
pNs->AddRef();
hRes = pNs->Initialize(wszNamespaceName);
}
}
CReleaseMe rm1(pNs);
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for namespace <%S>, error <0x%X>\n", wszNamespaceName, hRes));
}
//Retrieve the type of the next object in the import file
DWORD dwObjectType;
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
//Loop through all things that hang off this namespace
while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_NAMESPACE_END_TAG))
{
//Classes and namespaces are the only valid things to hang off a namespace
switch (dwObjectType)
{
case A51_EXPORT_CLASS_TAG:
{
//TODO: Need to create an empty class to pass through here!
hRes = ImportClass(pNs, NULL, NULL);
break;
}
case A51_EXPORT_NAMESPACE_TAG:
{
hRes = ImportNamespace();
break;
}
default:
hRes = WBEM_E_FAILED;
break;
}
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
}
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for child classes/namespace <%S>, error <0x%X>\n", wszNamespaceName, hRes));
}
return hRes;
}
/*=============================================================================
*
* A51Import::ImportClass
*
* Class Block:
* DWORD dwObjectType = A51_EXPORT_CLASS_TAG
* DWORD dwClassNameSize
* BYTE wszClassName[dwClassNameSize] = Class name (my_class_name)
* DWORD dwClassObjectSize
* BYTE adwClassObject[dwClassObjectSize]
*
*=============================================================================
*/
HRESULT A51Import::ImportClass(CNamespaceHandle *pNs,
_IWmiObject *pOldParentClass,
_IWmiObject *pNewParentClass)
{
HRESULT hRes;
DWORD dwLength = 0;
_IWmiObject *pOldClass = NULL;
_IWmiObject *pNewClass = NULL;
wchar_t *wszClassName = NULL;
//Retrieve the class name from the import file
hRes = ReadBufferWithLength(&dwLength, (void**) &wszClassName);
CVectorDeleteMe<wchar_t> vdm1(wszClassName );
{//scope to free everything we don't need when recursing to lower levels
//Retrieve the class object from the import file
BYTE *pClassBlob = NULL;
if (SUCCEEDED(hRes))
{
DEBUGTRACE((LOG_WBEMCORE, "Class import for class <%S>\n", wszClassName));
hRes = ReadBufferWithLength(&dwLength, (void**) &pClassBlob);
}
CVectorDeleteMe<BYTE> vdm2(pClassBlob);
//For Skip Mode we have to read everything from the import file, but not process anything
//until the flag is reset...
if (!m_bSkipMode)
{
//if pOldParentClass is NULL, we need to create a blank class
if (SUCCEEDED(hRes) && (pOldParentClass == NULL))
{
hRes = pNs->GetObjectByPath(L"", 0, IID__IWmiObject, (void**)&pOldParentClass);
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, GetObjectByPath(L\"\",...)\n", wszClassName, hRes));
}
}
//Create the current version of this class
if (SUCCEEDED(hRes))
{
hRes = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_CLASS, dwLength, pClassBlob, &pOldClass);
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, Merge\n", wszClassName, hRes));
}
}
//Now we need to upgrade this class based on the new parent class...
_IWmiObject *pTmpNewClass = NULL;
if (SUCCEEDED(hRes))
{
hRes = pOldClass->Upgrade(pNewParentClass, 0, &pTmpNewClass );
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, Upgrade\n", wszClassName, hRes));
}
}
CReleaseMe rm2(pTmpNewClass );
//Write the new class back to the repository if it is not a system class
if (SUCCEEDED(hRes) && (wszClassName[0] != L'_'))
{
hRes = BeginTransaction();
if (SUCCEEDED(hRes))
{
try
{
CEventCollector aEvents;
hRes = pNs->PutObject(IID__IWmiObject, pTmpNewClass , WBEM_FLAG_UPDATE_FORCE_MODE,
WMIDB_HANDLE_TYPE_COOKIE, 0, aEvents);
if (FAILED(hRes))
{
AbortTransaction();
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, PutObject\n", wszClassName, hRes));
}
else
{
hRes = CommitTransaction();
if (FAILED(hRes))
{
AbortTransaction();
}
}
}
catch (...)
{
AbortTransaction();
throw;
}
}
}
//Now we need to get that object back from the repository before we do anything
if (SUCCEEDED(hRes))
{
hRes = pNs->GetObjectByPath(wszClassName, 0, IID__IWmiObject, (void**)&pNewClass);
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, GetObjectByPath(wszClassName,...)\n", wszClassName, hRes));
}
if (hRes == WBEM_E_NOT_FOUND)
{
m_bSkipMode = true;
hRes = WBEM_S_NO_ERROR;
}
}
}
}
CReleaseMe rm1(pOldClass);
CReleaseMe rm3(pNewClass);
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>\n", wszClassName, hRes));
}
//Process the next object...
DWORD dwObjectType;
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
//Loop through all things that hang off this class
while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_CLASS_END_TAG))
{
//Classes and namespaces are the only valid things to hang off a namespace
switch (dwObjectType)
{
case A51_EXPORT_CLASS_TAG:
{
hRes = ImportClass(pNs, pOldClass, pNewClass);
break;
}
case A51_EXPORT_INST_TAG:
{
hRes = ImportInstance(pNs, pOldClass, pNewClass);
break;
}
default:
hRes = WBEM_E_FAILED;
break;
}
if (SUCCEEDED(hRes))
{
hRes = ReadObjectType(&dwObjectType);
}
}
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for child classes/instances <%S>, error <0x%X>\n", wszClassName, hRes));
}
m_bSkipMode = false;
return hRes;
}
/*=============================================================================
*
* A51Import::ImportInstance
*
* Instance Block - key of type string
* DWORD dwObjectType = A51_EXPORT_INST_TAG
* DWORD dwInstanceKeySize
* BYTE dwInstanceKey[dwInstanceKeySize] = Instance key
* DWORD dwInstanceObjectSize
* BYTE adwInstanceObject[dwInstanceObjectSize]
*
*=============================================================================
*/
HRESULT A51Import::ImportInstance(CNamespaceHandle *pNs,
_IWmiObject *pOldParentClass,
_IWmiObject *pNewParentClass)
{
HRESULT hRes;
DWORD dwLength = 0;
//Retrieve the key string from the import file
wchar_t *wszKeyString = NULL;
hRes = ReadBufferWithLength(&dwLength, (void**) &wszKeyString) ;
CVectorDeleteMe<wchar_t> vdm1(wszKeyString);
//Retrieve the instance object from the import file
BYTE *pInstBlob = NULL;
if (SUCCEEDED(hRes))
{
DEBUGTRACE((LOG_WBEMCORE, "Instance import for instance <%S>\n", wszKeyString));
hRes = ReadBufferWithLength(&dwLength, (void**) &pInstBlob);
}
CVectorDeleteMe<BYTE> vdm2(pInstBlob);
if (!m_bSkipMode)
{
_IWmiObject *pOldInstance = NULL;
//Merge the old instance part with the old instance class
if (SUCCEEDED(hRes))
{
hRes = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE,
dwLength, pInstBlob, &pOldInstance);
}
CReleaseMe rm1(pOldInstance);
//Upgrade the instance to work with the new class
_IWmiObject *pNewInstance = NULL;
if (SUCCEEDED(hRes))
{
hRes = pOldInstance->Upgrade(pNewParentClass, 0, &pNewInstance);
}
CReleaseMe rm2(pNewInstance);
//Put the instance into the repository
if (SUCCEEDED(hRes))
{
hRes = BeginTransaction();
if (SUCCEEDED(hRes))
{
try
{
CEventCollector aEvents;
hRes = pNs->PutObject(IID__IWmiObject, pNewInstance, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, aEvents);
if (SUCCEEDED(hRes))
{
hRes = CommitTransaction();
if (FAILED(hRes))
{
AbortTransaction();
}
}
else
{
AbortTransaction();
}
}
catch (...)
{
AbortTransaction();
throw;
}
}
}
}
if (FAILED(hRes))
{
ERRORTRACE((LOG_WBEMCORE, "Instance import failed for instance <%S>, error <0x%X>\n", wszKeyString, hRes));
}
return hRes;
}
/*=============================================================================
*
* A51Import::ReadBufferWithLength
*
*=============================================================================
*/
HRESULT A51Import::ReadBufferWithLength(DWORD *pdwBufferSize, void **ppBuffer)
{
HRESULT hRes = WBEM_S_NO_ERROR;
DWORD dwSize;
//Write buffer length
if (!ReadFile(m_hFile, pdwBufferSize, sizeof(DWORD), &dwSize, NULL) || (dwSize != sizeof(DWORD)))
{
hRes = WBEM_E_FAILED;
}
if (SUCCEEDED(hRes))
{
*ppBuffer = (void*)new BYTE[*pdwBufferSize];
if (*ppBuffer == NULL)
hRes = WBEM_E_OUT_OF_MEMORY;
}
//Write buffer
if (SUCCEEDED(hRes) &&
(!ReadFile(m_hFile, *ppBuffer, *pdwBufferSize, &dwSize, NULL) || (*pdwBufferSize != dwSize)))
{
hRes = WBEM_E_FAILED;
}
if (FAILED(hRes))
{
delete [] *ppBuffer;
*ppBuffer = NULL;
*pdwBufferSize = 0;
}
return hRes;
}
/*=============================================================================
*
* A51Import::ReadObjectType
*
*
*=============================================================================
*/
HRESULT A51Import::ReadObjectType(DWORD *pdwObjectType)
{
HRESULT hRes = WBEM_S_NO_ERROR;
DWORD dwSize;
if (!ReadFile(m_hFile, pdwObjectType, sizeof(DWORD), &dwSize, NULL) || (dwSize != sizeof(DWORD)))
{
hRes = WBEM_E_FAILED;
}
return hRes;
}
/*=============================================================================
*
* A51Import::BeginTransaction
*
*
*=============================================================================
*/
HRESULT A51Import::BeginTransaction()
{
return A51TranslateErrorCode(g_Glob.GetFileCache()->BeginTransaction());
}
/*=============================================================================
*
* A51Import::CommitTransaction
*
*
*=============================================================================
*/
HRESULT A51Import::CommitTransaction()
{
return A51TranslateErrorCode(g_Glob.GetFileCache()->CommitTransaction());
}
/*=============================================================================
*
* A51Import::AbortTransaction
*
*
*=============================================================================
*/
HRESULT A51Import::AbortTransaction()
{
return A51TranslateErrorCode(g_Glob.GetFileCache()->AbortTransaction());
}