795 lines
18 KiB
C++
795 lines
18 KiB
C++
#include "catalog.h"
|
|
#include "catmeta.h"
|
|
#include "WriterGlobalHelper.h"
|
|
#include "Writer.h"
|
|
#include "LocationWriter.h"
|
|
#include "MBPropertyWriter.h"
|
|
#include "MBCollectionWriter.h"
|
|
#include "MBSchemaWriter.h"
|
|
#include "WriterGlobals.h"
|
|
|
|
#define MAX_BUFFER 2048
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Initializes global lengths.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT InitializeLengths()
|
|
{
|
|
g_cchBeginFile = wcslen(g_wszBeginFile);
|
|
g_cchEndFile = wcslen(g_wszEndFile);
|
|
g_cchBeginLocation = wcslen(g_BeginLocation);
|
|
g_cchLocation = wcslen(g_Location);
|
|
g_cchEndLocationBegin = wcslen(g_EndLocationBegin);
|
|
g_cchEndLocationEnd = wcslen(g_EndLocationEnd);
|
|
g_cchCloseQuoteBraceRtn = wcslen(g_CloseQuoteBraceRtn);
|
|
g_cchRtn = wcslen(g_Rtn);
|
|
g_cchEqQuote = wcslen(g_EqQuote);
|
|
g_cchQuoteRtn = wcslen(g_QuoteRtn);
|
|
g_cchTwoTabs = wcslen(g_TwoTabs);
|
|
g_cchNameEq = wcslen(g_NameEq);
|
|
g_cchIDEq = wcslen(g_IDEq);
|
|
g_cchValueEq = wcslen(g_ValueEq);
|
|
g_cchTypeEq = wcslen(g_TypeEq);
|
|
g_cchUserTypeEq = wcslen(g_UserTypeEq);
|
|
g_cchAttributesEq = wcslen(g_AttributesEq);
|
|
g_cchBeginGroup = wcslen(g_BeginGroup);
|
|
g_cchEndGroup = wcslen(g_EndGroup);
|
|
g_cchBeginCustomProperty = wcslen(g_BeginCustomProperty);
|
|
g_cchEndCustomProperty = wcslen(g_EndCustomProperty);
|
|
g_cchZeroHex = wcslen(g_ZeroHex);
|
|
g_cchBeginComment = wcslen(g_BeginComment);
|
|
g_cchEndComment = wcslen(g_EndComment);
|
|
|
|
|
|
BYTE_ORDER_MASK = 0xFEFF;
|
|
UTF8_SIGNATURE = 0x00BFBBEF;
|
|
|
|
g_cchUnknownName = wcslen(g_wszUnknownName);
|
|
g_cchUT_Unknown = wcslen(g_UT_Unknown);
|
|
g_cchMaxBoolStr = wcslen(g_wszFalse);
|
|
|
|
g_cchHistorySlash = wcslen(g_wszHistorySlash);
|
|
g_cchMinorVersionExt = wcslen(g_wszMinorVersionExt);
|
|
g_cchDotExtn = wcslen(g_wszDotExtn);
|
|
|
|
g_cchTrue = wcslen(g_wszTrue);
|
|
g_cchFalse = wcslen(g_wszFalse);
|
|
|
|
g_cchTemp = 1024;
|
|
g_cchBeginSchema = wcslen(g_wszBeginSchema);
|
|
g_cchEndSchema = wcslen(g_wszEndSchema);
|
|
g_cchBeginCollection = wcslen(g_wszBeginCollection);
|
|
g_cchSchemaGen = wcslen(g_wszSchemaGen);
|
|
g_cchInheritsFrom = wcslen(g_wszInheritsFrom);
|
|
g_cchEndCollection = wcslen(g_wszEndCollection);
|
|
g_cchBeginPropertyShort = wcslen(g_wszBeginPropertyShort);
|
|
g_cchMetaFlagsExEq = wcslen(g_wszMetaFlagsExEq);
|
|
g_cchEndPropertyShort = wcslen(g_wszEndPropertyShort);
|
|
g_cchBeginPropertyLong = wcslen(g_wszBeginPropertyLong);
|
|
g_cchPropIDEq = wcslen(g_wszPropIDEq);
|
|
g_cchPropTypeEq = wcslen(g_wszPropTypeEq);
|
|
g_cchPropUserTypeEq = wcslen(g_wszPropUserTypeEq);
|
|
g_cchPropAttributeEq = wcslen(g_wszPropAttributeEq);
|
|
|
|
g_cchPropMetaFlagsEq = wcslen(g_wszPropMetaFlagsEq);
|
|
g_cchPropMetaFlagsExEq = wcslen(g_wszPropMetaFlagsExEq);
|
|
g_cchPropDefaultEq = wcslen(g_wszPropDefaultEq);
|
|
g_cchPropMinValueEq = wcslen(g_wszPropMinValueEq);
|
|
g_cchPropMaxValueEq = wcslen(g_wszPropMaxValueEq);
|
|
g_cchEndPropertyLongNoFlag = wcslen(g_wszEndPropertyLongNoFlag);
|
|
g_cchEndPropertyLongBeforeFlag = wcslen(g_wszEndPropertyLongBeforeFlag);
|
|
g_cchEndPropertyLongAfterFlag = wcslen(g_wszEndPropertyLongAfterFlag);
|
|
g_cchBeginFlag = wcslen(g_wszBeginFlag);
|
|
g_cchFlagValueEq = wcslen(g_wszFlagValueEq);
|
|
g_cchEndFlag = wcslen(g_wszEndFlag);
|
|
|
|
g_cchOr = wcslen(g_wszOr);
|
|
g_cchOrManditory = wcslen(g_wszOrManditory);
|
|
g_cchFlagIDEq = wcslen(g_wszFlagIDEq);
|
|
g_cchContainerClassListEq = wcslen(g_wszContainerClassListEq);
|
|
|
|
g_cchSlash = wcslen(g_wszSlash);
|
|
g_cchLM = wcslen(g_wszLM);
|
|
g_cchSchema = wcslen(g_wszSchema);
|
|
g_cchSlashSchema = wcslen(g_wszSlashSchema);
|
|
g_cchSlashSchemaSlashProperties = wcslen(g_wszSlashSchemaSlashProperties);
|
|
g_cchSlashSchemaSlashPropertiesSlashNames = wcslen(g_wszSlashSchemaSlashPropertiesSlashNames);
|
|
g_cchSlashSchemaSlashPropertiesSlashTypes = wcslen(g_wszSlashSchemaSlashPropertiesSlashTypes);
|
|
g_cchSlashSchemaSlashPropertiesSlashDefaults = wcslen(g_wszSlashSchemaSlashPropertiesSlashDefaults);
|
|
g_cchSlashSchemaSlashClasses = wcslen(g_wszSlashSchemaSlashClasses);
|
|
g_cchEmptyMultisz = 2;
|
|
g_cchEmptyWsz = 1;
|
|
g_cchComma = wcslen(g_wszComma);
|
|
g_cchMultiszSeperator = wcslen(g_wszMultiszSeperator);
|
|
|
|
return S_OK;
|
|
|
|
} // InitializeLengths
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Creates the CWriterGlobalHelper object - the object that has all the ISTs
|
|
to the meta tables - and initializess it.
|
|
|
|
Arguments:
|
|
|
|
[in] Bool indicating if we should fail if the bin file is absent.
|
|
There are some scenarios in which we can tolerate this, and some
|
|
where we dont - hence the distinction.
|
|
|
|
[out] new CWriterGlobalHelper object.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT GetGlobalHelper(BOOL i_bFailIfBinFileAbsent,
|
|
CWriterGlobalHelper** ppCWriterGlobalHelper)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
static BOOL bInitializeLengths = FALSE;
|
|
CWriterGlobalHelper* pCWriterGlobalHelper = NULL;
|
|
|
|
*ppCWriterGlobalHelper = NULL;
|
|
|
|
if(!bInitializeLengths)
|
|
{
|
|
//
|
|
// Initialize lengths once.
|
|
//
|
|
|
|
::InitializeLengths();
|
|
bInitializeLengths = TRUE;
|
|
}
|
|
|
|
//
|
|
// TODO: Is this an in-out parameter?
|
|
//
|
|
|
|
if(NULL != *ppCWriterGlobalHelper)
|
|
{
|
|
delete *ppCWriterGlobalHelper;
|
|
*ppCWriterGlobalHelper = NULL;
|
|
}
|
|
|
|
pCWriterGlobalHelper = new CWriterGlobalHelper();
|
|
if(NULL == pCWriterGlobalHelper)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pCWriterGlobalHelper->InitializeGlobals(i_bFailIfBinFileAbsent);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
delete pCWriterGlobalHelper;
|
|
pCWriterGlobalHelper = NULL;
|
|
return hr;
|
|
}
|
|
|
|
*ppCWriterGlobalHelper = pCWriterGlobalHelper;
|
|
|
|
return S_OK;
|
|
|
|
} // GetGlobalHelper
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CWriter
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--***************************************************************************/
|
|
CWriter::CWriter()
|
|
{
|
|
m_wszFile = NULL;
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
m_bCreatedFile = FALSE;
|
|
m_pCWriterGlobalHelper = NULL;
|
|
m_pISTWrite = NULL;
|
|
m_cbBufferUsed = 0;
|
|
|
|
} // Constructor CWriter
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CWriter
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--***************************************************************************/
|
|
CWriter::~CWriter()
|
|
{
|
|
if(NULL != m_wszFile)
|
|
{
|
|
delete [] m_wszFile;
|
|
m_wszFile = NULL;
|
|
}
|
|
if(m_bCreatedFile &&
|
|
(INVALID_HANDLE_VALUE != m_hFile || NULL != m_hFile)
|
|
)
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
else
|
|
{
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
if(NULL != m_pISTWrite)
|
|
{
|
|
m_pISTWrite->Release();
|
|
m_pISTWrite = NULL;
|
|
}
|
|
|
|
//
|
|
// Global helper is created externally, no need to delete here
|
|
//
|
|
|
|
} // Constructor CWriter
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Initialization for CWriter.
|
|
|
|
Arguments:
|
|
|
|
[in] FileName.
|
|
[in] Pointer to the CWriterGlobalHelper object that has all the meta
|
|
table information. We assume that this pointer is valid for the
|
|
duration of the writer object being initialized.
|
|
[in] Filehandle.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::Initialize(LPCWSTR wszFile,
|
|
CWriterGlobalHelper* i_pCWriterGlobalHelper,
|
|
HANDLE hFile)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
ISimpleTableDispenser2* pISTDisp = NULL;
|
|
IAdvancedTableDispenser* pISTAdvanced = NULL;
|
|
|
|
//
|
|
// TODO: Assert that everything is NULL
|
|
//
|
|
|
|
//
|
|
// Save file name and handle.
|
|
//
|
|
|
|
m_wszFile = new WCHAR[wcslen(wszFile)+1];
|
|
if(NULL == m_wszFile)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
wcscpy(m_wszFile, wszFile);
|
|
|
|
m_hFile = hFile;
|
|
|
|
//
|
|
// Initialized the used buffer count to zero.
|
|
//
|
|
|
|
m_cbBufferUsed = 0;
|
|
|
|
//
|
|
// Save the global helper object that has all the ISTs to all the meta
|
|
// tables. Assumption: i_pCWriterGlobalHelper will be valid for the
|
|
// lifetime of the writer object.
|
|
//
|
|
|
|
m_pCWriterGlobalHelper = i_pCWriterGlobalHelper;
|
|
|
|
hr = GetSimpleTableDispenser (WSZ_PRODUCT_IIS, 0, &pISTDisp);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = pISTDisp->QueryInterface(IID_IAdvancedTableDispenser, (LPVOID*)&pISTAdvanced);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// This IST is used as a cache to save the contents of a location. It
|
|
// used to be local to the location writer object (locationwriter.cpp).
|
|
// But it was moved to the writer object for perf because location
|
|
// writer is created for each location. The cache is cleared for each
|
|
// location by calling TODO
|
|
//
|
|
|
|
hr = pISTAdvanced->GetMemoryTable(wszDATABASE_METABASE,
|
|
wszTABLE_MBProperty,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
eST_QUERYFORMAT_CELLS,
|
|
fST_LOS_READWRITE,
|
|
&m_pISTWrite);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if(NULL != pISTAdvanced)
|
|
{
|
|
pISTAdvanced->Release();
|
|
pISTAdvanced = NULL;
|
|
}
|
|
|
|
if(NULL != pISTDisp)
|
|
{
|
|
pISTDisp->Release();
|
|
pISTDisp = NULL;
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // CWriter::Initialize
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Creates the file.
|
|
|
|
Arguments:
|
|
|
|
[in] Security attributes.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::ConstructFile(PSECURITY_ATTRIBUTES pSecurityAtrributes)
|
|
{
|
|
m_hFile = CreateFileW(m_wszFile,
|
|
GENERIC_WRITE,
|
|
0,
|
|
pSecurityAtrributes,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if(INVALID_HANDLE_VALUE == m_hFile)
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
m_bCreatedFile = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
} // CWriter::ConstructFile
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Writes the begin tags depending on whats being written (schema or data)
|
|
|
|
Arguments:
|
|
|
|
[in] Writer type - schema or metabase data.
|
|
[in] Security attributes.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::BeginWrite(eWriter eType,
|
|
PSECURITY_ATTRIBUTES pSecurityAtrributes)
|
|
{
|
|
ULONG dwBytesWritten = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
if((NULL == m_hFile) || (INVALID_HANDLE_VALUE == m_hFile))
|
|
{
|
|
hr = ConstructFile(pSecurityAtrributes);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if(!WriteFile(m_hFile,
|
|
(LPVOID)&UTF8_SIGNATURE,
|
|
sizeof(BYTE)*3,
|
|
&dwBytesWritten,
|
|
NULL))
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
if(eWriter_Metabase == eType)
|
|
{
|
|
hr = WriteToFile((LPVOID)g_wszBeginFile,
|
|
g_cchBeginFile);
|
|
}
|
|
else if(eWriter_Schema == eType)
|
|
{
|
|
hr = WriteToFile((LPVOID)g_wszBeginSchema,
|
|
g_cchBeginSchema);
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // CWriter::BeginWrite
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Writes the end tags depending on whats being written (schema or data)
|
|
Or if the write is being aborted, and the file has been created by the
|
|
writer, it cleans up the file.
|
|
|
|
Arguments:
|
|
|
|
[in] Writer type - schema or metabase data or abort
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::EndWrite(eWriter eType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch(eType)
|
|
{
|
|
case eWriter_Abort:
|
|
|
|
//
|
|
// Abort the write and return
|
|
//
|
|
|
|
if(m_bCreatedFile &&
|
|
((INVALID_HANDLE_VALUE != m_hFile) && (NULL != m_hFile))
|
|
)
|
|
{
|
|
//
|
|
// We created the file - delete it.
|
|
//
|
|
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
|
|
if(NULL != m_wszFile)
|
|
{
|
|
if(!DeleteFileW(m_wszFile))
|
|
{
|
|
hr= HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
break;
|
|
|
|
case eWriter_Metabase:
|
|
|
|
hr = WriteToFile((LPVOID)g_wszEndFile,
|
|
g_cchEndFile,
|
|
TRUE);
|
|
break;
|
|
|
|
case eWriter_Schema:
|
|
|
|
hr = WriteToFile((LPVOID)g_wszEndSchema,
|
|
g_cchEndSchema,
|
|
TRUE);
|
|
break;
|
|
|
|
default:
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(SetEndOfFile(m_hFile))
|
|
{
|
|
if(!FlushFileBuffers(m_hFile))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
|
|
} // CWriter::EndWrite
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Writes the data to the buffer. If the buffer is full, it forces a flush
|
|
to disk. It also forces a flush to disk if it is told to do so.
|
|
|
|
Arguments:
|
|
|
|
[in] Data
|
|
[in] Count of bytes to write
|
|
[in] Bool to indicate force flush or not.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::WriteToFile(LPVOID pvData,
|
|
DWORD cchData,
|
|
BOOL bForceFlush)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cbData = cchData *sizeof(WCHAR);
|
|
ULONG cchRemaining = cchData;
|
|
|
|
//
|
|
// TODO: Assert m_hFile is non-null
|
|
//
|
|
|
|
if((m_cbBufferUsed + cbData) > g_cbMaxBuffer)
|
|
{
|
|
ULONG iData = 0;
|
|
//
|
|
// If the data cannot be put in the global buffer, flush the contents
|
|
// of the global buffer to disk.
|
|
//
|
|
|
|
hr = FlushBufferToDisk();
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// m_cbBufferUsed should be zero now. If you still cannot accomodate
|
|
// the data split it up write into buffer.
|
|
//
|
|
|
|
while( cbData > g_cbMaxBuffer)
|
|
{
|
|
|
|
hr = WriteToFile(&(((LPWSTR)pvData)[iData]),
|
|
g_cchMaxBuffer,
|
|
bForceFlush);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
iData = iData + g_cchMaxBuffer;
|
|
cbData = cbData - g_cbMaxBuffer;
|
|
cchRemaining = cchRemaining - g_cchMaxBuffer;
|
|
|
|
}
|
|
|
|
hr = WriteToFile(&(((LPWSTR)pvData)[iData]),
|
|
cchRemaining,
|
|
bForceFlush);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// memcpy( (&(g_Buffer[g_cbBufferUsed])), &(((LPWSTR)pvData)[iData]), cbData);
|
|
// g_cbBufferUsed = g_cbBufferUsed + cbData;
|
|
|
|
}
|
|
else
|
|
{
|
|
memcpy( (&(m_Buffer[m_cbBufferUsed])), pvData, cbData);
|
|
m_cbBufferUsed = m_cbBufferUsed + cbData;
|
|
|
|
if(TRUE == bForceFlush)
|
|
{
|
|
hr = FlushBufferToDisk();
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // CWriter::WriteToFile
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Converts the data in the buffer (UNICODE) to UTF8 and writes the contents
|
|
to the file.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::FlushBufferToDisk()
|
|
{
|
|
DWORD dwBytesWritten = 0;
|
|
int cb = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
cb = WideCharToMultiByte(CP_UTF8, // Convert to UTF8
|
|
NULL, // Must be NULL
|
|
LPWSTR(m_Buffer), // Unicode string to convert.
|
|
m_cbBufferUsed/sizeof(WCHAR), // cch in string.
|
|
(LPSTR)m_BufferMultiByte, // buffer for new string
|
|
g_cbMaxBufferMultiByte, // size of buffer
|
|
NULL,
|
|
NULL);
|
|
if(!cb)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
if(!WriteFile(m_hFile,
|
|
(LPVOID)m_BufferMultiByte,
|
|
cb,
|
|
&dwBytesWritten,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
m_cbBufferUsed = 0;
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
|
|
} // CWriter::FlushBufferToDisk
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new location writer, initializes it and hands it out.
|
|
|
|
Arguments:
|
|
|
|
[out] Location Writer
|
|
[in] Location
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::GetLocationWriter(CLocationWriter** ppCLocationWriter,
|
|
LPCWSTR wszLocation)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppCLocationWriter = new CLocationWriter();
|
|
if(NULL == *ppCLocationWriter)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = (*ppCLocationWriter)->Initialize((CWriter*)(this),
|
|
wszLocation);
|
|
|
|
return hr;
|
|
|
|
} // CWriter::GetLocationWriter
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new schema writer, initializes it and hands it out.
|
|
|
|
Arguments:
|
|
|
|
[out] Schema Writer
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--***************************************************************************/
|
|
HRESULT CWriter::GetMetabaseSchemaWriter(CMBSchemaWriter** ppSchemaWriter)
|
|
{
|
|
*ppSchemaWriter = new CMBSchemaWriter((CWriter*)(this));
|
|
if(NULL == *ppSchemaWriter)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
} // CWriter::GetMetabaseSchemaWriter
|
|
|
|
|
|
|