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.
729 lines
14 KiB
729 lines
14 KiB
// TranxMgr.cpp: implementation for the CTranxMgr
|
|
//
|
|
// Copyright (c)1997-2001 Microsoft Corporation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
#include "precomp.h"
|
|
|
|
#include "XMLReader.h"
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::CXMLContent
|
|
|
|
Functionality:
|
|
|
|
Trivial.
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None as any constructor
|
|
|
|
Notes:
|
|
if you create any local members, think about initialize them here.
|
|
|
|
*/
|
|
|
|
CXMLContent::CXMLContent ()
|
|
: m_dwTotalElements(0),
|
|
m_hOutFile(NULL),
|
|
m_bFinished(false),
|
|
m_bInSection(false),
|
|
m_bSingleArea(true)
|
|
{
|
|
}
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::~CXMLContent
|
|
|
|
Functionality:
|
|
|
|
Trivial.
|
|
|
|
Virtual:
|
|
|
|
Yes.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None as any destructor
|
|
|
|
Notes:
|
|
if you create any local members, think about releasing them here.
|
|
|
|
*/
|
|
|
|
CXMLContent::~CXMLContent()
|
|
{
|
|
if (m_hOutFile != NULL)
|
|
{
|
|
::CloseHandle(m_hOutFile);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::startElement
|
|
|
|
Functionality:
|
|
|
|
Analyze the elements. If the element is what we are interested in,
|
|
then we will cache the information.
|
|
|
|
Virtual:
|
|
|
|
Yes.
|
|
|
|
Arguments:
|
|
|
|
pwchNamespaceUri - The namespace URI.
|
|
|
|
cchNamespaceUri - The length for the namespace URI.
|
|
|
|
pwchLocalName - The local name string.
|
|
|
|
cchLocalName - The length of the local name.
|
|
|
|
pwchQName - The QName (with prefix) or, if QNames are not available, an empty string.
|
|
|
|
cchQName - The length of the QName.
|
|
|
|
pAttributes - COM interface to the attribute object.
|
|
|
|
Return Value:
|
|
|
|
Success:
|
|
|
|
S_OK;
|
|
|
|
Failure:
|
|
|
|
E_FAIL (this causes the parser not to continue parsing).
|
|
|
|
Notes:
|
|
|
|
See MSDN ISAXContentHandler::startElement for detail. We must maintain our handler
|
|
to stay compatible with MSDN's specification.
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::startElement (
|
|
IN const wchar_t * pwchNamespaceUri,
|
|
IN int cchNamespaceUri,
|
|
IN const wchar_t * pwchLocalName,
|
|
IN int cchLocalName,
|
|
IN const wchar_t * pwchQName,
|
|
IN int cchQName,
|
|
IN ISAXAttributes * pAttributes
|
|
)
|
|
{
|
|
|
|
//
|
|
// If we have finished then we will stop here.
|
|
//
|
|
|
|
if ( m_bFinished )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
++m_dwTotalElements;
|
|
|
|
//
|
|
// if we are not in our section, we will only need to carry out
|
|
// further if this element is a Section element
|
|
//
|
|
|
|
if (m_bInSection == false && _wcsicmp(pwchQName, L"Section") == 0)
|
|
{
|
|
LPWSTR pArea = NULL;
|
|
if (GetAttributeValue(pAttributes, L"Area", &pArea))
|
|
{
|
|
m_bInSection = (_wcsicmp(m_bstrSecArea, L"All") == 0 || _wcsicmp(pArea, m_bstrSecArea) == 0);
|
|
|
|
//
|
|
// $undone:shawnwu, put some header information, currently, hard coded for SCE's INF file
|
|
//
|
|
|
|
if (_wcsicmp(L"Sce_Core", pArea) == 0)
|
|
{
|
|
WriteContent(L"[Unicode]", NULL);
|
|
WriteContent(L"Unicode", L"yes");
|
|
WriteContent(L"[Version]", NULL);
|
|
WriteContent(L"$CHICAGO$", NULL);
|
|
WriteContent(L"Revision", L"1");
|
|
WriteContent(L"\r\n", NULL);
|
|
WriteContent(L"[System Access]", NULL);
|
|
}
|
|
WriteContent(L"\r\n", NULL);
|
|
}
|
|
|
|
delete [] pArea;
|
|
}
|
|
|
|
//
|
|
// if not in our section, don't bother to continue
|
|
//
|
|
|
|
if (m_bInSection == false)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (m_bInElement == false && _wcsicmp(pwchQName, m_bstrElement) == 0)
|
|
{
|
|
m_bInElement = true;
|
|
|
|
//
|
|
// $undone:shawnwu, consider writing some element comments?
|
|
//
|
|
}
|
|
|
|
if (m_bInElement == false)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
int iAttribCount = 0;
|
|
|
|
pAttributes->getLength(&iAttribCount);
|
|
|
|
LPWSTR pszPropName = NULL;
|
|
LPWSTR pszPropValue = NULL;
|
|
|
|
if (GetAttributeValue(pAttributes, L"Name", &pszPropName))
|
|
{
|
|
|
|
//
|
|
// In real time, we will do something with the (name, value) pair
|
|
// since we are just testing here, write it to the file
|
|
//
|
|
|
|
if (GetAttributeValue(pAttributes, L"Value", &pszPropValue))
|
|
{
|
|
WriteContent(pszPropName, pszPropValue);
|
|
}
|
|
|
|
delete [] pszPropName;
|
|
pszPropName = NULL;
|
|
|
|
delete [] pszPropValue;
|
|
pszPropValue = NULL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::endElement
|
|
|
|
Functionality:
|
|
|
|
Analyze the elements. We may decide that this is the end of our parsing need
|
|
depending on our settings.
|
|
|
|
Virtual:
|
|
|
|
Yes.
|
|
|
|
Arguments:
|
|
|
|
pwchNamespaceUri - The namespace URI.
|
|
|
|
cchNamespaceUri - The length for the namespace URI.
|
|
|
|
pwchLocalName - The local name string.
|
|
|
|
cchLocalName - The length of the local name.
|
|
|
|
pwchQName - The QName (with prefix) or, if QNames are not available, an empty string.
|
|
|
|
cchQName - The length of the QName.
|
|
|
|
Return Value:
|
|
|
|
Success:
|
|
|
|
S_OK;
|
|
|
|
Failure:
|
|
|
|
E_FAIL (this causes the parser not to continue parsing).
|
|
|
|
Notes:
|
|
|
|
See MSDN ISAXContentHandler::endElement for detail. We must maintain our handler
|
|
to stay compatible with MSDN's specification.
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::endElement (
|
|
IN const wchar_t * pwchNamespaceUri,
|
|
IN int cchNamespaceUri,
|
|
IN const wchar_t * pwchLocalName,
|
|
IN int cchLocalName,
|
|
IN const wchar_t * pwchQName,
|
|
IN int cchQName
|
|
)
|
|
{
|
|
//
|
|
// if we have seen the section ended, we are done.
|
|
//
|
|
|
|
if (m_bInSection && _wcsicmp(pwchQName, L"Section") == 0)
|
|
{
|
|
m_bFinished = m_bSingleArea;
|
|
m_bInSection = false;
|
|
}
|
|
|
|
if (m_bInElement && _wcsicmp(pwchQName, m_bstrElement) == 0)
|
|
{
|
|
m_bInElement = false;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::startDocument()
|
|
{
|
|
m_bFinished = false;
|
|
m_bInElement = false;
|
|
m_bInSection = false;
|
|
m_dwTotalElements = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::endDocument ()
|
|
{
|
|
LPCWSTR pszOutFile = m_bstrOutputFile;
|
|
|
|
if (pszOutFile && *pszOutFile != L'\0')
|
|
{
|
|
//
|
|
// testing code.
|
|
//
|
|
|
|
WCHAR pszValue[100];
|
|
|
|
swprintf(pszValue, L"%d", m_dwTotalElements);
|
|
|
|
WriteContent(L"\r\nTotal Elements parsed: ", pszValue);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::putDocumentLocator (
|
|
IN ISAXLocator *pLocator
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::startPrefixMapping (
|
|
IN const wchar_t * pwchPrefix,
|
|
IN int cchPrefix,
|
|
IN const wchar_t * pwchUri,
|
|
IN int cchUri
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::endPrefixMapping (
|
|
IN const wchar_t * pwchPrefix,
|
|
IN int cchPrefix
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::characters (
|
|
IN const wchar_t * pwchChars,
|
|
IN int cchChars
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::ignorableWhitespace (
|
|
IN const wchar_t * pwchChars,
|
|
IN int cchChars
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::processingInstruction (
|
|
IN const wchar_t * pwchTarget,
|
|
IN int cchTarget,
|
|
IN const wchar_t * pwchData,
|
|
IN int cchData
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLContent::skippedEntity (
|
|
IN const wchar_t * pwchName,
|
|
IN int cchName
|
|
)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::GetAttributeValue
|
|
|
|
Functionality:
|
|
|
|
Private helper. Given the attribute's name, we will return the attribute's value.
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pAttributes - COM interface to the attribute object.
|
|
|
|
pszTestName - The name of the attributes we want the value of.
|
|
|
|
ppszAttrVal - Receives the attribute's value if found.
|
|
|
|
Return Value:
|
|
|
|
true if the named attribute is found;
|
|
|
|
false otherwise.
|
|
|
|
Notes:
|
|
Caller is responsible for releasing the memory allocated to the
|
|
out parameter.
|
|
|
|
*/
|
|
|
|
bool
|
|
CXMLContent::GetAttributeValue (
|
|
IN ISAXAttributes * pAttributes,
|
|
IN LPCWSTR pszAttrName,
|
|
OUT LPWSTR * ppszAttrVal
|
|
)
|
|
{
|
|
//
|
|
// caller is responsible for passing valid parameters
|
|
//
|
|
|
|
*ppszAttrVal = NULL;
|
|
|
|
int iAttribCount = 0;
|
|
|
|
pAttributes->getLength(&iAttribCount);
|
|
|
|
const wchar_t * pszName;
|
|
const wchar_t * pszValue;
|
|
|
|
int iNameLen;
|
|
int iValLen;
|
|
|
|
for ( int i = 0; i < iAttribCount; i++ )
|
|
{
|
|
HRESULT hr = pAttributes->getLocalName(i, &pszName, &iNameLen);
|
|
|
|
if (SUCCEEDED(hr) && wcsncmp(pszAttrName, pszName, iNameLen) == 0)
|
|
{
|
|
hr = pAttributes->getValue(i, &pszValue, &iValLen);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppszAttrVal = new WCHAR[iValLen + 1];
|
|
if (*ppszAttrVal != NULL)
|
|
{
|
|
wcscpy(*ppszAttrVal, pszValue);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::GetAttributeValue
|
|
|
|
Functionality:
|
|
|
|
Private helper. Given the index, we will return the attribute's name and its value.
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pAttributes - COM interface to the attribute object.
|
|
|
|
iIndex - The index of the attribute we want.
|
|
|
|
ppszAttrName - Receives the name of the attributes we want.
|
|
|
|
ppszAttrVal - Receives the attribute's value if found.
|
|
|
|
Return Value:
|
|
|
|
true if the named attribute is found;
|
|
|
|
false otherwise.
|
|
|
|
Notes:
|
|
|
|
Caller is responsible for releasing the memory allocated to both
|
|
out parameters.
|
|
*/
|
|
|
|
bool
|
|
CXMLContent::GetAttributeValue (
|
|
IN ISAXAttributes * pAttributes,
|
|
IN int iIndex,
|
|
OUT LPWSTR * ppszAttrName,
|
|
OUT LPWSTR * ppszAttrVal
|
|
)
|
|
{
|
|
|
|
//
|
|
// caller is responsible for passing valid parameters
|
|
//
|
|
|
|
*ppszAttrName = NULL;
|
|
*ppszAttrVal = NULL;
|
|
|
|
const wchar_t * pszName;
|
|
const wchar_t * pszValue;
|
|
|
|
int iNameLen;
|
|
int iValLen;
|
|
|
|
HRESULT hr = pAttributes->getLocalName(iIndex, &pszName, &iNameLen);
|
|
|
|
if (SUCCEEDED(hr) && iNameLen > 0)
|
|
{
|
|
hr = pAttributes->getValue(iIndex, &pszValue, &iValLen);
|
|
if (SUCCEEDED(hr) && iValLen > 0)
|
|
{
|
|
*ppszAttrName = new WCHAR[iNameLen + 1];
|
|
*ppszAttrVal = new WCHAR[iValLen + 1];
|
|
|
|
if (*ppszAttrName != NULL && *ppszAttrVal != NULL)
|
|
{
|
|
wcsncpy(*ppszAttrName, pszName, iNameLen);
|
|
(*ppszAttrName)[iNameLen] = L'\0';
|
|
|
|
wcsncpy(*ppszAttrVal, pszValue, iValLen);
|
|
(*ppszAttrVal)[iValLen] = L'\0';
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::WriteContent
|
|
|
|
Functionality:
|
|
|
|
Testing function. This determines which section area this
|
|
reader is interested in and which element of the section
|
|
this reader will process.
|
|
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pszSecArea - The Area attribute of the section the reader will process.
|
|
|
|
pszElement - The name of the element the reader will process.
|
|
|
|
bOneAreaOnly- Whether we will only process one area.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
*/
|
|
|
|
void
|
|
CXMLContent::SetSection (
|
|
IN LPCWSTR pszSecArea,
|
|
IN LPCWSTR pszElement,
|
|
IN bool bOneAreaOnly
|
|
)
|
|
{
|
|
m_bstrSecArea = pszSecArea;
|
|
m_bstrElement = pszElement;
|
|
m_bSingleArea = bOneAreaOnly;
|
|
}
|
|
|
|
|
|
/*
|
|
Routine Description:
|
|
|
|
Name:
|
|
|
|
CXMLContent::WriteContent
|
|
|
|
Functionality:
|
|
|
|
Private helper for testing (for now).
|
|
|
|
Given the name and value pair, we will write <name>=<value> into the output file.
|
|
|
|
Virtual:
|
|
|
|
No.
|
|
|
|
Arguments:
|
|
|
|
pszName - The name of the pair.
|
|
|
|
pszValue - The value of the pair. Can be NULL. In that case, we will only
|
|
write the pszName as a separate line.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
*/
|
|
|
|
void
|
|
CXMLContent::WriteContent (
|
|
IN LPCWSTR pszName,
|
|
IN LPCWSTR pszValue
|
|
)
|
|
{
|
|
if (m_hOutFile == NULL)
|
|
{
|
|
m_hOutFile = ::CreateFile (m_bstrOutputFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (m_hOutFile != NULL)
|
|
{
|
|
DWORD dwBytesWritten = 0;
|
|
|
|
::WriteFile (m_hOutFile,
|
|
(LPCVOID) pszName,
|
|
wcslen(pszName) * sizeof(WCHAR),
|
|
&dwBytesWritten,
|
|
NULL
|
|
);
|
|
|
|
if (pszValue != NULL)
|
|
{
|
|
::WriteFile (m_hOutFile,
|
|
(LPCVOID) L"=",
|
|
sizeof(WCHAR),
|
|
&dwBytesWritten,
|
|
NULL
|
|
);
|
|
|
|
::WriteFile (m_hOutFile,
|
|
(LPCVOID) pszValue,
|
|
wcslen(pszValue) * sizeof(WCHAR),
|
|
&dwBytesWritten,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
//
|
|
// a new line
|
|
//
|
|
|
|
::WriteFile (m_hOutFile,
|
|
(LPCVOID) L"\r\n",
|
|
2 * sizeof(WCHAR),
|
|
&dwBytesWritten,
|
|
NULL
|
|
);
|
|
}
|
|
}
|