|
|
//***************************************************************************
//
// (c) 2001 by Microsoft Corp. All Rights Reserved.
//
//***************************************************************************
#include "precomp.h"
#include <wbemcomn.h>
#include "a51tools.h"
#include "objheap.h"
#include "index.h"
#include "creposit.h"
//*******************************************************************
//*******************************************************************
long CObjectHeap::Initialize(CPageSource * pAbstractSource, WCHAR * wszBaseName, DWORD dwBaseNameLen) { if (m_bInit) return ERROR_SUCCESS; long lRes; lRes = m_Heap.Initialize(pAbstractSource);
if(lRes != ERROR_SUCCESS) return lRes;
lRes = m_Index.Initialize(dwBaseNameLen, wszBaseName, pAbstractSource); if(lRes != ERROR_SUCCESS) return lRes;
m_bInit = TRUE;
return lRes; }
//*******************************************************************
//*******************************************************************
long CObjectHeap::Uninitialize(DWORD dwShutDownFlags) { if (!m_bInit) return ERROR_SUCCESS; m_Index.Shutdown(dwShutDownFlags);
m_Heap.Shutdown(dwShutDownFlags);
m_bInit = FALSE;
return ERROR_SUCCESS; }
//*******************************************************************
//*******************************************************************
void CObjectHeap::InvalidateCache() { m_Index.InvalidateCache(); m_Heap.InvalidateCache(); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::GetIndexFileName(LPCWSTR wszFilePath, CFileName& wszIndexFileName) { WIN32_FIND_DATAW wfd;
long lRes = m_Index.FindFirst(wszFilePath, &wfd, NULL); if(lRes != ERROR_SUCCESS) { return lRes; }
StringCchCopyW(wszIndexFileName, wszIndexFileName.Length(), wfd.cFileName); return ERROR_SUCCESS; }
//*******************************************************************
//*******************************************************************
long CObjectHeap::GetFileInfo(LPCWSTR wszFilePath, TPage *pnPage, TOffset* pnOffset, DWORD* pdwLength) { CFileName wszIndexFileName; if(wszIndexFileName == NULL) return ERROR_OUTOFMEMORY;
long lRes = GetIndexFileName(wszFilePath, wszIndexFileName); if(lRes != ERROR_SUCCESS) return lRes;
return ParseInfoFromIndexFile(wszIndexFileName, pnPage, pnOffset, pdwLength); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::ParseInfoFromIndexFile(LPCWSTR wszIndexFileName, TPage *pnPage, TOffset* pnOffset, DWORD* pdwLength) { WCHAR* pDot = wcschr(wszIndexFileName, L'.'); if(pDot == NULL) return ERROR_INVALID_PARAMETER;
WCHAR* pwc = pDot+1; *pnPage = 0; while(*pwc && *pwc != L'.') { *pnPage = (*pnPage * 10) + (*pwc - '0'); pwc++; }
if(*pwc != L'.') return ERROR_INVALID_PARAMETER;
pwc++;
*pnOffset = 0; while(*pwc && *pwc != L'.') { *pnOffset = (*pnOffset * 10) + (*pwc - '0'); pwc++; }
if(*pwc != L'.') return ERROR_INVALID_PARAMETER;
pwc++;
*pdwLength = 0; while(*pwc && *pwc != L'.') { *pdwLength = (*pdwLength * 10) + (*pwc - '0'); pwc++; }
return ERROR_SUCCESS; }
//*******************************************************************
//*******************************************************************
long CObjectHeap::CreateIndexFile(LPCWSTR wszFilePath, TPage nPage, TOffset nOffset, DWORD dwLength) { //
// Simply append the numbers to the file path
//
CFileName wszIndexFilePath; if(wszIndexFilePath == NULL) return ERROR_OUTOFMEMORY;
StringCchPrintfW(wszIndexFilePath, wszIndexFilePath.Length(), L"%s.%u.%u.%u", wszFilePath, nPage, nOffset, dwLength);
return CreateZeroLengthFile(wszIndexFilePath); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::DeleteIndexFile(LPCWSTR wszFilePath, LPCWSTR wszIndexFileName) { //
// Construct the full path to the index file by concatenating the directory
// of the original file with the name
//
CFileName wszIndexFilePath; if(wszIndexFilePath == NULL) return ERROR_OUTOFMEMORY;
WCHAR* pwcLastSlash = wcsrchr(wszFilePath, L'\\'); if(pwcLastSlash == NULL) return ERROR_INVALID_PARAMETER;
int nPrefixLen = (pwcLastSlash - wszFilePath + 1); memcpy(wszIndexFilePath, wszFilePath, nPrefixLen * sizeof(WCHAR));
StringCchCopyW(wszIndexFilePath + nPrefixLen, wszIndexFilePath.Length() - nPrefixLen, wszIndexFileName); return DeleteZeroLengthFile(wszIndexFilePath); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::CreateZeroLengthFile(LPCWSTR wszFilePath) { return m_Index.Create(wszFilePath); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::DeleteZeroLengthFile(LPCWSTR wszFilePath) { return m_Index.Delete(wszFilePath); } //*******************************************************************
//*******************************************************************
long CObjectHeap::WriteAllocation(DWORD dwDataLength, BYTE* pData, TPage *pnPage, TOffset *pnOffset) { return m_Heap.WriteNewBuffer(dwDataLength, pData, pnPage, pnOffset); } //*******************************************************************
//*******************************************************************
long CObjectHeap::WriteExistingAllocation(TPage nOldPage, TOffset nOldOffset, DWORD dwDataLength, BYTE *pBuffer, DWORD *pnNewPage, DWORD *pnNewOffset) { return m_Heap.WriteExistingBuffer(dwDataLength, pBuffer, nOldPage, nOldOffset, pnNewPage, pnNewOffset); }
//*******************************************************************
//*******************************************************************
long CObjectHeap::ReadAllocation(TPage nPage, TOffset nOffset, DWORD dwDataLength, BYTE* pBuffer) { //
// Prepare a buffer with the complete allocation
//
BYTE* pAllocation; DWORD dwReadLength;
long lRes = m_Heap.ReadBuffer(nPage, nOffset, &pAllocation, &dwReadLength); if(lRes != ERROR_SUCCESS) return lRes;
if (dwReadLength != dwDataLength) { _ASSERT(0, L"WinMgmt: Buffer length is not the expected length!\n"); }
memcpy(pBuffer, pAllocation, dwDataLength);
delete [] pAllocation;
return ERROR_SUCCESS; }
//*******************************************************************
//*******************************************************************
long CObjectHeap::WriteObject(LPCWSTR wszFilePath1, LPCWSTR wszFilePath2, DWORD dwBufferLen, BYTE* pBuffer) { if (!m_bInit) return ERROR_INVALID_OPERATION;
long lRes;
if(dwBufferLen == 0) { //
// We do not use the heap for 0-length files, we create them directly
//
return CreateZeroLengthFile(wszFilePath1); }
//
// Now, check if this file already exists
//
CFileName wszIndexFileName1; if(wszIndexFileName1 == NULL) return ERROR_OUTOFMEMORY;
lRes = GetIndexFileName(wszFilePath1, wszIndexFileName1); if(lRes != ERROR_FILE_NOT_FOUND && lRes != ERROR_SUCCESS) return lRes;
if(lRes == ERROR_SUCCESS) { //
// Already there.
//
TPage nOldPage; TOffset nOldOffset; DWORD dwOldLength; TPage nNewPage; TOffset nNewOffset;
lRes = ParseInfoFromIndexFile(wszIndexFileName1, &nOldPage, &nOldOffset, &dwOldLength); if(lRes != ERROR_SUCCESS) return lRes;
//
// Enough space in place --- just write the data and update the
// length
//
lRes = WriteExistingAllocation(nOldPage, nOldOffset, dwBufferLen, pBuffer, &nNewPage, &nNewOffset); if(lRes != ERROR_SUCCESS) return lRes;
if((dwOldLength != dwBufferLen) || (nOldPage != nNewPage) || (nOldOffset != nNewOffset)) {
//
// One of the bits of the path has changed so we need to re-create the index
//
lRes = DeleteIndexFile(wszFilePath1, wszIndexFileName1); if(lRes != ERROR_SUCCESS) return lRes;
lRes = CreateIndexFile(wszFilePath1, nNewPage, nNewOffset, dwBufferLen); if(lRes != ERROR_SUCCESS) return lRes;
if (wszFilePath2) { CFileName wszIndexFileName2; if(wszIndexFileName2 == NULL) return ERROR_OUTOFMEMORY; lRes = GetIndexFileName(wszFilePath2, wszIndexFileName2); if(lRes != ERROR_SUCCESS) return lRes;
lRes = DeleteIndexFile(wszFilePath2, wszIndexFileName2); if(lRes != ERROR_SUCCESS) return lRes;
lRes = CreateIndexFile(wszFilePath2, nNewPage, nNewOffset, dwBufferLen); if(lRes != ERROR_SUCCESS) return lRes; } }
return ERROR_SUCCESS; }
//
// it wasn't there
//
TPage nPage; TOffset nOffset;
lRes = WriteAllocation(dwBufferLen, pBuffer, &nPage, &nOffset); if(lRes != ERROR_SUCCESS) return lRes;
lRes = CreateIndexFile(wszFilePath1, nPage, nOffset, dwBufferLen); if(lRes != ERROR_SUCCESS) return lRes;
if (wszFilePath2) lRes = CreateIndexFile(wszFilePath2, nPage, nOffset, dwBufferLen); return lRes; }
//***********************************************************************
//***********************************************************************
long CObjectHeap::WriteLink(LPCWSTR wszLinkPath) { if (!m_bInit) return ERROR_INVALID_OPERATION;
return CreateZeroLengthFile(wszLinkPath); } //*******************************************************************
//*******************************************************************
long CObjectHeap::ReadObject(LPCWSTR wszFilePath, DWORD* pdwLength, BYTE** ppBuffer) { if (!m_bInit) return ERROR_INVALID_OPERATION;
long lRes;
//
// Find the file
//
TPage nPage; TOffset nOffset; lRes = GetFileInfo(wszFilePath, &nPage, &nOffset, pdwLength); if(lRes != ERROR_SUCCESS) return lRes;
//
// Read the allocation
//
*ppBuffer = (BYTE*)TempAlloc(*pdwLength); if(*ppBuffer == NULL) return ERROR_OUTOFMEMORY;
lRes = ReadAllocation(nPage, nOffset, *pdwLength, *ppBuffer); if(lRes != ERROR_SUCCESS) { TempFree(*ppBuffer); return lRes; }
return ERROR_SUCCESS; }
//*******************************************************************
//*******************************************************************
long CObjectHeap::DeleteLink(LPCWSTR wszFilePath) { if (!m_bInit) return ERROR_INVALID_OPERATION;
//
// Find the index file
//
CFileName wszIndexFileName; if(wszIndexFileName == NULL) return ERROR_OUTOFMEMORY;
long lRes = GetIndexFileName(wszFilePath, wszIndexFileName); if(lRes != ERROR_SUCCESS) { return lRes; }
//If we have any index information at the end of the path we need to add that to
//the main path and delete that. The delete requires an accurate path.
CFileName wszActualFileName; if(wszActualFileName == NULL) return ERROR_OUTOFMEMORY;
StringCchCopyW(wszActualFileName, wszActualFileName.Length(), wszFilePath); wchar_t *wszDot = wcschr(wszIndexFileName, L'.'); if (wszDot != NULL) StringCchCatW(wszActualFileName, wszActualFileName.Length(), wszDot);
return DeleteZeroLengthFile(wszActualFileName); } //*******************************************************************
//*******************************************************************
long CObjectHeap::DeleteObject(LPCWSTR wszFilePath) { if (!m_bInit) return ERROR_INVALID_OPERATION;
//
// Find the index file
//
CFileName wszIndexFileName; if(wszIndexFileName == NULL) return ERROR_OUTOFMEMORY;
long lRes = GetIndexFileName(wszFilePath, wszIndexFileName); if(lRes != ERROR_SUCCESS) return lRes;
//
// Delete the allocation
//
TPage nPage; TOffset nOffset; DWORD dwLength; lRes = ParseInfoFromIndexFile(wszIndexFileName, &nPage, &nOffset, &dwLength); if(lRes == ERROR_INVALID_PARAMETER) { _ASSERT(0, L"WinMgmt: Deleting an object that does not have details of where object is!\n"); return ERROR_INVALID_OPERATION; } lRes = m_Heap.DeleteBuffer(nPage, nOffset); if(lRes != ERROR_SUCCESS) return lRes; //
// Delete the index itself
//
lRes = DeleteIndexFile(wszFilePath, wszIndexFileName); if(lRes != ERROR_SUCCESS) return lRes;
return ERROR_SUCCESS; }
long CObjectHeap::DeleteNode(LPCWSTR wszNodeName) { long lRes = 0; void *handle; CFileName wszFileName; if (wszFileName == 0) return ERROR_OUTOFMEMORY; CFileName wszFullFileName; if (wszFullFileName == 0) return ERROR_OUTOFMEMORY; lRes = IndexEnumerationBegin(wszNodeName, &handle); if (lRes == ERROR_NO_MORE_FILES) lRes = 0; if (lRes) return lRes;
while ((lRes = IndexEnumerationNext(handle, wszFileName, true)) == ERROR_SUCCESS) { StringCchCopyW(wszFullFileName, MAX_PATH, g_Glob.GetRootDir()); StringCchCatW(wszFullFileName, MAX_PATH, L"\\"); StringCchCatW(wszFullFileName, MAX_PATH, wszFileName);
lRes = DeleteZeroLengthFile(wszFullFileName); if (lRes) { break; }
TPage nPage; TOffset nOffset; DWORD dwLength; lRes = ParseInfoFromIndexFile(wszFullFileName+g_Glob.GetRootDirLen(), &nPage, &nOffset, &dwLength); if(lRes != ERROR_INVALID_PARAMETER) { if (!KeyRootInstancePath(wszFullFileName+g_Glob.GetRootDirLen()+1)) { lRes = m_Heap.DeleteBuffer(nPage, nOffset); if(lRes != ERROR_SUCCESS) { break; } } }
}
IndexEnumerationEnd(handle); if (lRes == ERROR_NO_MORE_FILES) lRes = 0; return lRes; }
bool CObjectHeap::KeyRootInstancePath(const wchar_t *wszPath) { WCHAR* pDot = wcschr(wszPath, L'\\'); if(pDot == NULL) return false;
pDot++;
pDot = wcschr(pDot, L'\\'); if(pDot == NULL) return false;
pDot++;
if ((*pDot == L'I') && (*(pDot+1) == L'_')) return true; else return false; } long CObjectHeap::ObjectEnumerationBegin(const wchar_t *wszSearchPrefix, void **ppHandle) { return IndexEnumerationBegin(wszSearchPrefix, ppHandle); }
long CObjectHeap::ObjectEnumerationEnd(void *pHandle) { return IndexEnumerationEnd(pHandle); }
long CObjectHeap::ObjectEnumerationNext(void *pHandle, CFileName &wszFileName, BYTE **ppBlob, DWORD *pdwSize) { if (!m_bInit) return ERROR_INVALID_OPERATION; long lRes = m_Index.IndexEnumerationNext(pHandle, wszFileName);
if (lRes == ERROR_SUCCESS) { //We need to retrieve the object from the heap!
TPage nPage; TOffset nOffset; DWORD dwLength; lRes = ParseInfoFromIndexFile(wszFileName, &nPage, &nOffset, &dwLength); if(lRes == ERROR_INVALID_PARAMETER) lRes = ERROR_SUCCESS; //This is a plain enumeration, no blobs associated with it
else { //Remove extra stuff from end of string...
for (int nCount = 0, nIndex = wcslen(wszFileName); nCount != 3; nIndex --) { if (wszFileName[nIndex-1] == L'.') { if (++nCount == 3) wszFileName[nIndex-1] = L'\0'; }
} DWORD dwSize = 0; lRes = m_Heap.ReadBuffer(nPage, nOffset, ppBlob, &dwSize); if ((lRes == ERROR_SUCCESS) && (dwSize != dwLength)) { _ASSERT(0, L"WinMgmt: Buffer size is not the expected length!\n"); } *pdwSize = dwLength; } } return lRes; }
long CObjectHeap::ObjectEnumerationFree(void *pHandle, BYTE *pBlob) { if (!m_bInit) return ERROR_INVALID_OPERATION;
delete [] pBlob; return ERROR_SUCCESS; }
long CObjectHeap::IndexEnumerationBegin(const wchar_t *wszSearchPrefix, void **ppHandle) { if (!m_bInit) return ERROR_INVALID_OPERATION; return m_Index.IndexEnumerationBegin(wszSearchPrefix, ppHandle); } long CObjectHeap::IndexEnumerationEnd(void *pHandle) { if (!m_bInit) return ERROR_INVALID_OPERATION; return m_Index.IndexEnumerationEnd(pHandle); } long CObjectHeap::IndexEnumerationNext(void *pHandle, CFileName &wszFileName, bool bCopyFullPath) { if (!m_bInit) return ERROR_INVALID_OPERATION; long lRes = m_Index.IndexEnumerationNext(pHandle, wszFileName, bCopyFullPath);
if ((lRes == ERROR_SUCCESS) && !bCopyFullPath) { wchar_t *pDot = wcschr(wszFileName, L'.'); if (pDot) *pDot = L'\0'; }
return lRes; }
long CObjectHeap::FlushCaches() { long lRes = m_Index.FlushCaches(); if (lRes == 0) lRes = m_Heap.FlushCaches(); return lRes; }
long CObjectHeap::ReadNextIndex(CFileName &wszSearch, CFileName &wszNextIndex) { if (!m_bInit) return ERROR_INVALID_OPERATION;
return m_Index.ReadNextIndex(wszSearch, wszNextIndex); }
|