mirror of https://github.com/tongzx/nt5src
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.
622 lines
15 KiB
622 lines
15 KiB
/*++
|
|
|
|
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());
|
|
}
|
|
|