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.
402 lines
14 KiB
402 lines
14 KiB
/*++
|
|
|
|
Copyright (C) 1996-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
EXPORT.CPP
|
|
|
|
Abstract:
|
|
|
|
Exporting
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "Time.h"
|
|
#include "WbemCli.h"
|
|
#include "DbRep.h"
|
|
#include "Export.h"
|
|
#include "WbemUtil.h"
|
|
|
|
|
|
void CRepExporter::DumpInstanceString(INSTDEF* pInstDef, const wchar_t *wszKey, const wchar_t *pszClass)
|
|
{
|
|
if (wszKey)
|
|
{
|
|
//Dump an instance block header
|
|
DWORD dwSize = 0;
|
|
DWORD adwBuffer[2];
|
|
adwBuffer[0] = REP_EXPORT_INST_STR_TAG;
|
|
adwBuffer[1] = (wcslen(wszKey) + 1) * sizeof (wchar_t);
|
|
if ((WriteFile(g_hFile, adwBuffer, sizeof(adwBuffer), &dwSize, NULL) == 0) || (dwSize != sizeof(adwBuffer)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S header.\n", wszKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, wszKey, (wcslen(wszKey) + 1) * sizeof (wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(wszKey) + 1) * sizeof (wchar_t)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S.\n", wszKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
|
|
{
|
|
//Dump the block
|
|
DWORD dwSize = 0;
|
|
DWORD *pdwObjectStream = Fixup((DWORD*)pInstDef->m_poObjectStream);
|
|
DWORD dwCurSize = *(pdwObjectStream - 1);
|
|
dwCurSize -= GetMMFBlockOverhead();
|
|
if ((WriteFile(g_hFile, &dwCurSize, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
|
|
{
|
|
if (wszKey)
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of instance %S for class %S.\n", wszKey, pszClass));
|
|
}
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of class definition for class %S.\n", pszClass));
|
|
}
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, pdwObjectStream, dwCurSize, &dwSize, NULL) == 0) || (dwSize != dwCurSize))
|
|
{
|
|
if (wszKey)
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S.\n", wszKey, pszClass));
|
|
}
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write class definition for class %S.\n", pszClass));
|
|
}
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
}
|
|
void CRepExporter::DumpInstanceInt(INSTDEF* pInstDef, INT_PTR nKey, const wchar_t *pszClass)
|
|
{
|
|
{
|
|
//Dump an instance block header
|
|
DWORD dwSize = 0;
|
|
DWORD dwBuffer;
|
|
dwBuffer = REP_EXPORT_INST_INT_TAG;
|
|
if ((WriteFile(g_hFile, &dwBuffer, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S object and header.\n", nKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, &nKey, sizeof(INT_PTR), &dwSize, NULL) == 0) || (dwSize != sizeof(INT_PTR)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S object and header.\n", nKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
{
|
|
//Dump the block
|
|
DWORD dwSize = 0;
|
|
DWORD *pObjectStream = Fixup((DWORD*)pInstDef->m_poObjectStream);
|
|
DWORD dwCurSize = *(pObjectStream - 1);
|
|
dwCurSize -= GetMMFBlockOverhead();
|
|
if ((WriteFile(g_hFile, &dwCurSize, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of instance %%d for class %S.\n", nKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, pObjectStream, dwCurSize, &dwSize, NULL) == 0) || (dwSize != dwCurSize))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S.\n", nKey, pszClass));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
}
|
|
void CRepExporter::IterateKeyTree(const wchar_t *wszClassName, CLASSDEF *pOwningClass, AVLNode *pInstNode, BOOL bStringKey)
|
|
{
|
|
if (pInstNode->poLeft)
|
|
{
|
|
IterateKeyTree(wszClassName, pOwningClass, Fixup(pInstNode->poLeft), bStringKey);
|
|
}
|
|
|
|
//If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
|
|
INSTDEF *pInstDef = Fixup((INSTDEF*)pInstNode->poData);
|
|
if (Fixup(pInstDef->m_poOwningClass) == pOwningClass)
|
|
{
|
|
if (bStringKey)
|
|
DumpInstanceString(pInstDef, Fixup((wchar_t*)pInstNode->nKey), wszClassName);
|
|
else
|
|
DumpInstanceInt(pInstDef, pInstNode->nKey, wszClassName);
|
|
}
|
|
|
|
if (pInstNode->poRight)
|
|
{
|
|
IterateKeyTree(wszClassName, pOwningClass, Fixup(pInstNode->poRight), bStringKey);
|
|
}
|
|
}
|
|
|
|
void CRepExporter::DumpClass(CLASSDEF* pClassDef, const wchar_t *wszClassName)
|
|
{
|
|
DWORD dwSize = 0;
|
|
DWORD adwBuffer[6];
|
|
adwBuffer[0] = REP_EXPORT_CLASS_TAG;
|
|
adwBuffer[1] = (wcslen(wszClassName) + 1) * sizeof (wchar_t);
|
|
if ((WriteFile(g_hFile, adwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write clas %S header.\n", wszClassName));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, wszClassName, (wcslen(wszClassName) + 1) * sizeof (wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(wszClassName) + 1) * sizeof (wchar_t)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write clas %S class name.\n", wszClassName));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
|
|
DumpInstanceString(Fixup(pClassDef->m_poClassDef), NULL, wszClassName);
|
|
|
|
//Dump the children classes...
|
|
AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(Fixup(pClassDef->m_poOwningNs)->m_poClassTree))[0]));
|
|
IterateClassNodes(pTreeNode, Fixdown(pClassDef));
|
|
|
|
//Special cases! We do not dump instances for the following classes...
|
|
if ((_wcsicmp(wszClassName, L"__CIMOMIdentification") != 0))
|
|
{
|
|
//If we own the key tree, then we need to iterate through this...
|
|
if (pClassDef->m_poKeyTree)
|
|
{
|
|
DWORD_PTR dwTreeNode = (((DWORD*)Fixup(pClassDef->m_poKeyTree))[0]);
|
|
if (dwTreeNode)
|
|
{
|
|
AVLNode *pTreeNode2 = Fixup((AVLNode*)dwTreeNode);
|
|
int keyType = GetAvlTreeNodeType(Fixup(pClassDef->m_poKeyTree));
|
|
IterateKeyTree(wszClassName, pClassDef, pTreeNode2, (keyType == 0x1f));
|
|
}
|
|
|
|
}
|
|
}
|
|
adwBuffer[0] = REP_EXPORT_CLASS_END_TAG;
|
|
adwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
|
|
memset(&(adwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
|
|
if ((WriteFile(g_hFile, adwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write class %S end marker.\n", wszClassName));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
|
|
void CRepExporter::IterateClassNodes(AVLNode *pClassNode, CLASSDEF *poParentClass)
|
|
{
|
|
if (pClassNode->poLeft)
|
|
{
|
|
IterateClassNodes(Fixup((AVLNode *)pClassNode->poLeft), poParentClass);
|
|
}
|
|
|
|
//If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
|
|
CLASSDEF *pClassDef = Fixup((CLASSDEF*)pClassNode->poData);
|
|
if (pClassDef->m_poSuperclass == poParentClass)
|
|
{
|
|
DumpClass(pClassDef, Fixup((wchar_t*)pClassNode->nKey));
|
|
}
|
|
|
|
if (pClassNode->poRight)
|
|
{
|
|
IterateClassNodes(Fixup((AVLNode *)pClassNode->poRight), poParentClass);
|
|
}
|
|
}
|
|
void CRepExporter::IterateChildNamespaceTree(AVLNode *pNsNode)
|
|
{
|
|
if (pNsNode->poLeft)
|
|
{
|
|
IterateChildNamespaceTree(Fixup((AVLNode *)pNsNode->poLeft));
|
|
}
|
|
|
|
//If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
|
|
NSREP *pNsDef = Fixup((NSREP*)pNsNode->poData);
|
|
DumpNamespace(pNsDef);
|
|
|
|
if (pNsNode->poRight)
|
|
{
|
|
IterateChildNamespaceTree(Fixup((AVLNode *)pNsNode->poRight));
|
|
}
|
|
}
|
|
|
|
void CRepExporter::IterateChildNamespaces(RepCollection *childNamespaces)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
DWORD_PTR dwItems;
|
|
|
|
dwType = ((DWORD*)childNamespaces)[0];
|
|
dwSize = ((DWORD*)childNamespaces)[1];
|
|
dwItems = ((DWORD*)childNamespaces)[2];
|
|
|
|
if ((dwType == 0) || (dwSize == 0))
|
|
return;
|
|
else if (dwType == 1)
|
|
{
|
|
//This is a pointer to a RepCollectionItem!
|
|
RepCollectionItem *pRepCollectionItem = Fixup((RepCollectionItem*)dwItems);
|
|
DumpNamespace(Fixup((NSREP*)pRepCollectionItem->poItem));
|
|
}
|
|
else if (dwType == 2)
|
|
{
|
|
CDbArray *pDbArray = Fixup((CDbArray*)dwItems);
|
|
RepCollectionItem** apNsRepItem;
|
|
apNsRepItem = Fixup((RepCollectionItem**)(((DWORD_PTR*)pDbArray)[3]));
|
|
for (DWORD i = 0; i != dwSize; i++)
|
|
{
|
|
DumpNamespace(Fixup((NSREP*)(Fixup(apNsRepItem[i])->poItem)));
|
|
}
|
|
}
|
|
else if (dwType == 3)
|
|
{
|
|
//This is a tree
|
|
AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(dwItems))[0]));
|
|
IterateChildNamespaceTree(pTreeNode);
|
|
}
|
|
else
|
|
{
|
|
//this is a bug!
|
|
}
|
|
}
|
|
|
|
void CRepExporter::DumpNamespace(NSREP *pNsRep)
|
|
{
|
|
wchar_t *pszCurNs = Fixup(pNsRep->m_poName);
|
|
|
|
DWORD dwSize = 0;
|
|
DWORD dwBuffer[6];
|
|
dwBuffer[0] = REP_EXPORT_NAMESPACE_TAG;
|
|
dwBuffer[1] = (wcslen(pszCurNs) + 1) * sizeof(wchar_t);
|
|
|
|
if ((WriteFile(g_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S header.\n", pszCurNs));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
if ((WriteFile(g_hFile, pszCurNs, (wcslen(pszCurNs) + 1) * sizeof(wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(pszCurNs) + 1) * sizeof(wchar_t)))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S.\n", pszCurNs));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
|
|
DumpNamespaceSecurity(pNsRep);
|
|
|
|
AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(pNsRep->m_poClassTree))[0]));
|
|
|
|
IterateClassNodes(pTreeNode, 0);
|
|
|
|
IterateChildNamespaces(Fixup(pNsRep->m_poNamespaces));
|
|
|
|
dwBuffer[0] = REP_EXPORT_NAMESPACE_END_TAG;
|
|
dwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
|
|
memset(&(dwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
|
|
if ((WriteFile(g_hFile, dwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S end marker.\n", pszCurNs));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
|
|
void CRepExporter::DumpNamespaceSecurity(NSREP *pNsRep)
|
|
{
|
|
//Default version does not have a security descriptor, so we need to
|
|
//just dump a blank entry.
|
|
DWORD dwSize = 0;
|
|
DWORD dwBuffer[2];
|
|
dwBuffer[0] = REP_EXPORT_NAMESPACE_SEC_TAG;
|
|
dwBuffer[1] = dwSize;
|
|
|
|
if ((WriteFile(g_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace security, %S.\n", Fixup(pNsRep->m_poName)));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
}
|
|
|
|
void CRepExporter::DumpRootBlock(DBROOT *pRootBlock)
|
|
{
|
|
if (pRootBlock->m_dwFlags & DB_ROOT_INUSE)
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write file header block.\n"));
|
|
throw FAILURE_DIRTY;
|
|
}
|
|
char *pBuffer = REP_EXPORT_FILE_START_TAG;
|
|
DWORD dwSizeBuffer = strlen(pBuffer);
|
|
DWORD dwSize = 0;
|
|
|
|
if ((WriteFile(g_hFile, pBuffer, dwSizeBuffer, &dwSize, NULL) == 0) || (dwSize != dwSizeBuffer))
|
|
{
|
|
throw(FAILURE_WRITE);
|
|
}
|
|
DumpNamespace(Fixup((NSREP*)pRootBlock->m_poRootNs));
|
|
|
|
DWORD dwBuffer[6];
|
|
dwBuffer[0] = REP_EXPORT_FILE_END_TAG;
|
|
dwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
|
|
memset(&(dwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
|
|
if ((WriteFile(g_hFile, dwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to write file trailer block.\n"));
|
|
throw FAILURE_WRITE;
|
|
}
|
|
|
|
}
|
|
|
|
void CRepExporter::DumpMMFHeader()
|
|
{
|
|
MMF_ARENA_HEADER *pMMFHeader = m_pDbArena->GetMMFHeader();
|
|
DumpRootBlock(Fixup((DBROOT*)pMMFHeader->m_dwRootBlock));
|
|
|
|
}
|
|
|
|
int CRepExporter::Export(CMMFArena2 *pDbArena, const TCHAR *pszFilename)
|
|
{
|
|
DWORD dwVersion = NULL;
|
|
HMODULE hModule = NULL;
|
|
const char *pszDllName = NULL;
|
|
int nRet = 0;
|
|
|
|
m_pDbArena = pDbArena;
|
|
|
|
g_hFile = CreateFile(pszFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (g_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
try
|
|
{
|
|
DumpMMFHeader();
|
|
CloseHandle(g_hFile);
|
|
}
|
|
catch (int dProblem)
|
|
{
|
|
switch(dProblem)
|
|
{
|
|
case FAILURE_DIRTY:
|
|
DEBUGTRACE((LOG_WBEMCORE, "Repository is marked as corrupt, therefore cannot export it.\n"));
|
|
break;
|
|
case FAILURE_WRITE:
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failure writing to the export file. May be out of disk space, or may not have write access to this directory.\n"));
|
|
break;
|
|
default:
|
|
DEBUGTRACE((LOG_WBEMCORE, "An unknown problem happened while traversing the repository.\n"));
|
|
break;
|
|
}
|
|
CloseHandle(g_hFile);
|
|
nRet = 1;
|
|
}
|
|
catch (...)
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Traversal of repository file failed. It may be corrupt.\n"));
|
|
CloseHandle(g_hFile);
|
|
DeleteFile(pszFilename);
|
|
nRet = 1;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Failed to create file %s to export the repository.\n", pszFilename));
|
|
nRet = 1;
|
|
}
|
|
return nRet;
|
|
}
|