Leaked source code of windows server 2003
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.
 
 
 
 
 
 

624 lines
18 KiB

#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();
}