|
|
#include "stdafx.hxx"
#include "vs_idl.hxx"
#include "vswriter.h"
#include "vsbackup.h"
#include "compont.h"
#include <debug.h>
#include <cwriter.h>
#include <lmshare.h>
#include <lmaccess.h>
#include <time.h>
//
// CWriterComponentsSelection class
//
CWriterComponentsSelection::CWriterComponentsSelection() { m_WriterId = GUID_NULL; m_uNumComponents = 0; m_uNumSubcomponents = 0; m_ppwszComponentLogicalPaths = NULL; m_ppwszSubcomponentLogicalPaths = NULL; }
CWriterComponentsSelection::~CWriterComponentsSelection() { if ((m_uNumComponents > 0) && (m_ppwszComponentLogicalPaths != NULL)) { for (UINT i=0; i<m_uNumComponents; i++) { if (m_ppwszComponentLogicalPaths[i] != NULL) { free(m_ppwszComponentLogicalPaths[i]); m_ppwszComponentLogicalPaths[i] = NULL; } }
free(m_ppwszComponentLogicalPaths); m_ppwszComponentLogicalPaths = NULL; m_uNumComponents = 0; }
if ((m_uNumSubcomponents > 0) && (m_ppwszSubcomponentLogicalPaths != NULL)) { for (UINT i=0; i<m_uNumSubcomponents; i++) { if (m_ppwszSubcomponentLogicalPaths[i] != NULL) { free(m_ppwszSubcomponentLogicalPaths[i]); m_ppwszSubcomponentLogicalPaths[i] = NULL; } }
free(m_ppwszSubcomponentLogicalPaths); m_ppwszSubcomponentLogicalPaths = NULL; m_uNumSubcomponents = 0; } }
void CWriterComponentsSelection::SetWriter ( IN VSS_ID WriterId ) { m_WriterId = WriterId; }
HRESULT CWriterComponentsSelection::AddSelectedComponent ( IN WCHAR* pwszComponentLogicalPath ) { return AddSelected(pwszComponentLogicalPath, m_ppwszComponentLogicalPaths, m_uNumComponents); }
HRESULT CWriterComponentsSelection::AddSelectedSubcomponent ( IN WCHAR* pwszSubcomponentLogicalPath ) { return AddSelected(pwszSubcomponentLogicalPath, m_ppwszSubcomponentLogicalPaths, m_uNumSubcomponents); }
HRESULT CWriterComponentsSelection::AddSelected ( IN WCHAR* pwszLogicalPath, WCHAR**& pwszLogicalPaths, UINT& uSize ) { if (m_WriterId == GUID_NULL) { // Don't allow adding components to NULL writer...
return E_UNEXPECTED; }
if (pwszLogicalPath == NULL) { return E_INVALIDARG; }
// A more clever implementation would allocate memory in chuncks, but this is just a test program...
PWCHAR *ppwzTemp = (PWCHAR *) realloc(pwszLogicalPaths, (uSize+1) * sizeof (PWCHAR)); if (ppwzTemp != NULL) { pwszLogicalPaths = ppwzTemp; pwszLogicalPaths[uSize] = NULL; } else { return E_OUTOFMEMORY; }
pwszLogicalPaths[uSize] = (PWCHAR) malloc((wcslen(pwszLogicalPath) + 1) * sizeof (WCHAR)); if (pwszLogicalPaths[uSize] != NULL) { wcscpy(pwszLogicalPaths[uSize], pwszLogicalPath); uSize++; } else { return E_OUTOFMEMORY; }
return S_OK; }
BOOL CWriterComponentsSelection::IsComponentSelected ( IN WCHAR* pwszComponentLogicalPath, IN WCHAR* pwszComponentName ) { return IsSelected(pwszComponentLogicalPath, pwszComponentName, m_ppwszComponentLogicalPaths, m_uNumComponents); }
BOOL CWriterComponentsSelection::IsSubcomponentSelected ( IN WCHAR* pwszSubcomponentLogicalPath, IN WCHAR* pwszSubcomponentName ) { return IsSelected(pwszSubcomponentLogicalPath, pwszSubcomponentName, m_ppwszSubcomponentLogicalPaths, m_uNumSubcomponents); }
BOOL CWriterComponentsSelection::IsSelected(IN WCHAR* pwszLogicalPath, IN WCHAR* pwszName, IN WCHAR** pwszLogicalPaths, IN UINT uSize) { if (m_WriterId == GUID_NULL) { // Don't allow query for NULL writer...
return FALSE; } if (uSize <= 0) { return FALSE; }
// A component matches if:
// 1. The selection criteria is on the logical-path of the leaf component OR
// 2. The selection criteria is <full-logical-path>\<component-name>
// 3. The selction criteria is component-name (only if logical-path is NULL)
for (UINT i=0; i<uSize; i++) { DWORD dwLen;
if (pwszLogicalPaths[i] == NULL) { continue; }
dwLen = (DWORD)wcslen(pwszLogicalPaths[i]);
if (pwszLogicalPath != NULL) { // Case 1.
if (_wcsnicmp(pwszLogicalPaths[i], pwszLogicalPath, dwLen) == 0 && pwszName == NULL) { return TRUE; }
// Case 2.
if (pwszName == NULL) { continue; } WCHAR* pwszTemp = wcsrchr(pwszLogicalPaths[i], L'\\'); if (pwszTemp == NULL) { continue; } if ((pwszTemp != pwszLogicalPaths[i]) && (*(pwszTemp+1) != '\0')) { dwLen = (DWORD)(pwszTemp - pwszLogicalPaths[i]); if ( (dwLen == wcslen(pwszLogicalPath)) && (_wcsnicmp(pwszLogicalPaths[i], pwszLogicalPath, dwLen) == 0) && (wcscmp(pwszTemp+1, pwszName) == 0) ) { return TRUE; } } } else { // Case 3.
if (pwszName == NULL) { continue; } if (_wcsnicmp(pwszLogicalPaths[i], pwszName, dwLen) == 0) { return TRUE; } } }
return FALSE; }
//
// CWritersSelection class
//
CWritersSelection::CWritersSelection() { m_lRef = 0; }
CWritersSelection::~CWritersSelection() { // Cleanup the Map
for(int nIndex = 0; nIndex < m_WritersMap.GetSize(); nIndex++) { CWriterComponentsSelection* pComponentsSelection = m_WritersMap.GetValueAt(nIndex); if (pComponentsSelection) { delete pComponentsSelection; } }
m_WritersMap.RemoveAll(); }
CWritersSelection* CWritersSelection::CreateInstance() { CWritersSelection* pObj = new CWritersSelection;
return pObj; }
STDMETHODIMP CWritersSelection::QueryInterface( IN REFIID iid, OUT void** pp ) { if (pp == NULL) return E_INVALIDARG; if (iid != IID_IUnknown) return E_NOINTERFACE;
AddRef(); IUnknown** pUnk = reinterpret_cast<IUnknown**>(pp); (*pUnk) = static_cast<IUnknown*>(this); return S_OK; }
ULONG CWritersSelection::AddRef() { return ::InterlockedIncrement(&m_lRef); }
ULONG CWritersSelection::Release() { LONG l = ::InterlockedDecrement(&m_lRef); if (l == 0) delete this; // We assume that we always allocate this object on the heap!
return l; }
STDMETHODIMP CWritersSelection::BuildChosenComponents ( WCHAR *pwszComponentsFileName ) { HRESULT hr = S_OK; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwBytesToRead = 0; DWORD dwBytesRead;
// Create the file
hFile = CreateFile(pwszComponentsFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { DWORD dwLastError = GetLastError(); wprintf(L"Invalid components file, CreateFile returned = %lu\n", dwLastError); return HRESULT_FROM_WIN32(dwLastError); }
if ((dwBytesToRead = GetFileSize(hFile, NULL)) <= 0) { CloseHandle(hFile); DWORD dwLastError = GetLastError(); wprintf(L"Invalid components file, GetFileSize returned = %lu\n", dwLastError); return HRESULT_FROM_WIN32(dwLastError); }
if (dwBytesToRead > 0x100000) { CloseHandle(hFile); wprintf(L"Invalid components file, Provide a file with a size of less than 1 MB\n"); return E_FAIL; }
char * pcBuffer = (PCHAR) malloc (dwBytesToRead); if (! pcBuffer) { CloseHandle(hFile); return E_OUTOFMEMORY; }
// Read the components info
if (! ReadFile(hFile, (LPVOID)pcBuffer, dwBytesToRead, &dwBytesRead, NULL)) { DWORD dwLastError = GetLastError(); CloseHandle(hFile); free (pcBuffer); wprintf(L"Invalid components file, ReadFile returned = %lu\n", dwLastError); return HRESULT_FROM_WIN32(dwLastError); }
CloseHandle(hFile);
if (dwBytesToRead != dwBytesRead) { free (pcBuffer); wprintf(L"Components selection file is supposed to have %lu bytes but only %lu bytes are read\n", dwBytesToRead, dwBytesRead); return E_FAIL; }
// Allocate a buffer to work with
WCHAR * pwcBuffer = (PWCHAR) malloc ((dwBytesToRead+1) * sizeof(WCHAR)); if (! pwcBuffer) { free (pcBuffer); return E_OUTOFMEMORY; }
// Simple pasring, assume ANSI, Format:
// "writer1-id": "component1.1-name", "component1.2-name",... ; "writer2-id": "component2.1-name", ...
CWriterComponentsSelection* pWriterComponents = NULL;
try { VSS_ID WriterId = GUID_NULL; BOOL bBeforeWriter = TRUE; BOOL bBeforeComponents = TRUE; BOOL bInString = FALSE; char* pcStart = NULL;
for (char* pcCurrent = pcBuffer; pcCurrent < (pcBuffer+dwBytesToRead); pcCurrent++) { switch (*pcCurrent) { case ':': if (bBeforeWriter && !bInString) { bBeforeWriter = FALSE; } else if (bBeforeComponents && !bInString) { bBeforeComponents = FALSE; } else if (!bInString) { throw(E_FAIL); } break;
case ';': if (bBeforeWriter || bInString) { throw(E_FAIL); } else { // If we have a valid writer - add it to the map
if ((pWriterComponents != NULL) && (WriterId != GUID_NULL)) { if (!m_WritersMap.Add(WriterId, pWriterComponents)) { delete pWriterComponents; throw E_OUTOFMEMORY; }
pWriterComponents = NULL; WriterId = GUID_NULL; }
bBeforeWriter = TRUE; } break;
case ',': if (bBeforeWriter || bInString) { throw(E_FAIL); } break;
case '"': if (! bInString) { // Mark string-start for later
pcStart = pcCurrent + 1; } else if (pcStart == pcCurrent) { // empty string - skip it
} else { // String ends - convert to WCHAR and process
DWORD dwSize = (DWORD)mbstowcs(pwcBuffer, pcStart, pcCurrent - pcStart); pwcBuffer[dwSize] = NULL; if (dwSize <= 0) { throw(E_FAIL); }
if (bBeforeWriter) { // If before-writer - must be a writer GUID
HRESULT hrConvert = CLSIDFromString(pwcBuffer, &WriterId); if ((! SUCCEEDED(hrConvert)) && (hrConvert != REGDB_E_WRITEREGDB)) { wprintf(L"A writer id in the components selection file is in invalid GUID format\n"); throw(E_FAIL); }
if (pWriterComponents != NULL) { // Previous writer info was not ended correctly
throw(E_FAIL); }
pWriterComponents = new CWriterComponentsSelection; if (pWriterComponents == NULL) { throw(E_OUTOFMEMORY); } pWriterComponents->SetWriter(WriterId); } else if (bBeforeComponents) { // Must be a component logical-path , name or logical-path\name
if (pWriterComponents != NULL) { pWriterComponents->AddSelectedComponent(pwcBuffer); } } else { // Must be a component logical-path , name or logical-path\name
if (pWriterComponents != NULL) { pWriterComponents->AddSelectedSubcomponent(pwcBuffer); } } }
// Flip in-string flag
bInString = (! bInString);
break;
case ' ': break;
case '\n': case '\t': case '\r': if (bInString) { throw(E_FAIL); }
break;
default: if (! bInString) { throw(E_FAIL); }
break;
} } }
catch (HRESULT hrParse) { hr = hrParse;
if (hr == E_FAIL) { wprintf(L"Invalid format of components selection file\n"); }
if (pWriterComponents != NULL) { // Error int he middle of writer-components creation (not added to the map yet...)
delete pWriterComponents; } }
free (pcBuffer); free (pwcBuffer);
return hr; } BOOL CWritersSelection::IsComponentSelected ( IN VSS_ID WriterId, IN WCHAR* pwszComponentLogicalPath, IN WCHAR* pwszComponentName ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { // No component is selected for this writer
return FALSE; }
// There are components selected for this writer, check if this specific one is selected
return pWriterComponents->IsComponentSelected(pwszComponentLogicalPath, pwszComponentName); }
BOOL CWritersSelection::IsSubcomponentSelected ( IN VSS_ID WriterId, IN WCHAR* pwszComponentLogicalPath, IN WCHAR* pwszComponentName ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { // No component is selected for this writer
return FALSE; }
// There are subccomponents selected for this writer, check if this specific one is selected
return pWriterComponents->IsSubcomponentSelected(pwszComponentLogicalPath, pwszComponentName); }
const WCHAR* const * CWritersSelection::GetComponents ( IN VSS_ID WriterId ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { return NULL; }
return pWriterComponents->GetComponents(); }
const WCHAR* const * CWritersSelection::GetSubcomponents ( IN VSS_ID WriterId ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { return NULL; }
return pWriterComponents->GetSubcomponents(); }
const UINT CWritersSelection::GetComponentsCount ( IN VSS_ID WriterId ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { return NULL; }
return pWriterComponents->GetComponentsCount(); }
const UINT CWritersSelection::GetSubcomponentsCount ( IN VSS_ID WriterId ) { CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId); if (pWriterComponents == NULL) { return NULL; }
return pWriterComponents->GetSubcomponentsCount(); }
|