|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name :
xmlupgrade.cxx
Abstract:
Classes that are used to upgrade the xml metabase and mbschema from one version to another
Author:
Christopher Achille (cachille)
Project:
Internet Services Setup
Revision History: September 2001: Created
--*/
#include "stdafx.h"
#include "buffer.hxx"
#include "xmlupgrade.hxx"
#include "acl.hxx"
// Constructor, initialize all the variables
//
CFileModify::CFileModify() { m_hReadFile = INVALID_HANDLE_VALUE; m_hWriteFile = INVALID_HANDLE_VALUE; m_buffData.Resize(CFILEMODIFY_BLOCKSIZE + 2); m_szCurrentData = (LPBYTE) m_buffData.QueryPtr(); m_dwSizeofData = 0; m_bUnicode = FALSE; *m_szReadFileName = '\0'; *m_szWriteFileName = '\0'; SetValue(m_szCurrentData, '\0'); }
// Destructor, close the file
//
CFileModify::~CFileModify() { // Just incase it has not been closed yet, close it
CloseFile(); }
// function: MoveXChars
//
// Move the pointer the number of characters specified
//
// Parameters:
// szCurrent - Pointer to a unicode or ansi string
// (type is determined by m_m_bUnicode)
//
// Return:
// Pointer to szCurrent + dwChars
//
LPBYTE CFileModify::MoveXChars(LPBYTE szCurrent, DWORD dwChars) { if ( m_bUnicode ) { return (LPBYTE) ( ( ( LPWSTR ) szCurrent ) + dwChars ); } else { return (LPBYTE) ( ( ( LPSTR ) szCurrent ) + dwChars ); } }
LPBYTE CFileModify::MoveXChars(LPVOID szCurrent, DWORD dwChars) { return MoveXChars( (LPBYTE) szCurrent, dwChars ); }
// function: SetValue
//
// Set the value at the location specified
//
// Parameters:
// szCurrent - Pointer to a unicode or ansi string
// (type is determined by m_m_bUnicode)
// dwValue - The value to put in the string
// dwOffset - Offset to add to szCurrent (in chars) (default of 0)
//
void CFileModify::SetValue(LPBYTE szCurrent, DWORD dwValue, DWORD dwOffset ) { LPBYTE szNewLocation = szCurrent;
if ( dwOffset ) { szNewLocation = MoveXChars(szCurrent,dwOffset); }
if ( m_bUnicode ) { * ( ( LPWSTR ) szNewLocation ) = (WCHAR) dwValue; } else { * ( ( LPSTR ) szNewLocation ) = (CHAR) dwValue; } }
void CFileModify::SetValue(PVOID szCurrent, DWORD dwValue, DWORD dwOffset ) { SetValue( (LPBYTE) szCurrent,dwValue,dwOffset); }
// function: CopyString
//
// Copy a string into the buffer
void CFileModify::CopyString(LPBYTE szCurrent, LPTSTR szInsertString) { while ( *szInsertString ) { SetValue(szCurrent,*szInsertString); GetNextChar(szCurrent); szInsertString++; } }
// function: AbortFile
//
// Abort the current file modification. So, we close the file handles, and delete the
// file that we wrote to
//
BOOL CFileModify::AbortFile() { BOOL bRet = TRUE;
if (m_hReadFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hReadFile); m_hReadFile = INVALID_HANDLE_VALUE; }
if (m_hWriteFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hWriteFile); m_hWriteFile = INVALID_HANDLE_VALUE; bRet = DeleteFile( m_szWriteFileName ); }
return bRet; }
// function: CloseFile
//
// Close all of the files, and write all the data to disk
//
BOOL CFileModify::CloseFile() { BOOL bWrite = m_hWriteFile != INVALID_HANDLE_VALUE; BOOL bRet = TRUE;
if ( bWrite ) { // Dump the rest of the input file to the output one.
while ( ReadNextChunk() ) { // Move to the end of the block, so it will all be written
m_szCurrentData = MoveXChars( m_buffData.QueryPtr(), m_dwSizeofData ); }
if ( m_dwSizeofData ) { // The last ReadNextChunk failed because we could not read anymore,
// lets call it one more time to flush the rest of the data in the buffer
m_szCurrentData = MoveXChars( m_buffData.QueryPtr(), m_dwSizeofData ); ReadNextChunk(); } }
if (m_hReadFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hReadFile); m_hReadFile = INVALID_HANDLE_VALUE; }
if (m_hWriteFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hWriteFile); m_hWriteFile = INVALID_HANDLE_VALUE; }
if ( bWrite ) { bRet = FALSE; if ( DeleteFile( m_szReadFileName ) ) { MoveFile( m_szWriteFileName, m_szReadFileName ); bRet = TRUE; } }
return bRet; }
// function: OpenFile
//
// This function opens a readonly handle to the file specified in szFileName,
// also a second File handle will be opened with write only access under the
// name szFileName+".tmp". This is for temporary storage for the new file
//
// Parameters:
// szFileName - The filename of the file to read
// bModify - Are we going to be modifing this file or not?
//
// Return
// TRUE - Read and Write files we successfully opened
// FALSE - Failure to open one of the files
//
BOOL CFileModify::OpenFile(LPTSTR szFileName, BOOL bModify) { CSecurityDescriptor AdminAcl;
if ( ( _tcslen(szFileName) - _tcslen(_T(".tmp")) ) >= _MAX_PATH ) { return FALSE; }
if ( !AdminAcl.CreateAdminDAcl() ) { // We could not create an admin acl, so lets exit
return FALSE; }
// First abort the last file, if one was opened
AbortFile();
_tcscpy(m_szReadFileName,szFileName); _tcscpy(m_szWriteFileName,szFileName); _tcscat(m_szWriteFileName,_T(".tmp"));
m_hReadFile = CreateFile( m_szReadFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( m_hReadFile == INVALID_HANDLE_VALUE ) { return FALSE; } if ( bModify ) { m_hWriteFile = CreateFile( m_szWriteFileName, GENERIC_WRITE, 0, AdminAcl.QuerySA(), CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL );
if ( m_hWriteFile == INVALID_HANDLE_VALUE ) { // Close Read File and return
AbortFile(); return FALSE; } }
m_szCurrentData = (LPBYTE) m_buffData.QueryPtr(); m_dwSizeofData = 0; m_bUnicode = FALSE;
if ( ReadNextChunk() ) {
if ( ( m_dwSizeofData > 3 ) && ( *( ( LPBYTE ) m_buffData.QueryPtr() ) == 0xEF ) && ( *( ( LPBYTE ) m_buffData.QueryPtr() + 1 ) == 0xBB ) && ( *( ( LPBYTE ) m_buffData.QueryPtr() + 2 ) == 0xBF ) ) { // It is UTF8 Encoded
m_bUnicode = FALSE; m_szCurrentData = (LPBYTE) m_buffData.QueryPtr() + 3; } else if ( ( m_dwSizeofData >= 2 ) && ( *( ( LPBYTE ) m_buffData.QueryPtr() ) == 0xFF ) && ( *( ( LPBYTE ) m_buffData.QueryPtr() + 1 ) == 0xFE) ) { // It is Unicode
m_bUnicode = TRUE; m_szCurrentData = (LPBYTE) m_buffData.QueryPtr() + 2; } }
return TRUE; }
// function: ResizeData
//
// Resize the data buffer to the size specified
// never shrink the buffer itself, just exand it
//
// Parameters:
// dwNewSize - The new size needed
BOOL CFileModify::ResizeData(DWORD dwNewSize) { BOOL bRet = TRUE;
if (m_buffData.QuerySize() < (dwNewSize + 2) ) { DWORD dwCurrentOffset = (DWORD) (DWORD_PTR) (m_szCurrentData - (LPBYTE) m_buffData.QueryPtr());
if ( !m_buffData.Resize(dwNewSize + 2) ) { // We failed to allocate the memory necessary
bRet = FALSE; }
if (dwCurrentOffset <= dwNewSize) { m_szCurrentData = (LPBYTE) m_buffData.QueryPtr() + dwCurrentOffset; } else { ASSERT(FALSE); m_szCurrentData = (LPBYTE) m_buffData.QueryPtr(); } }
return bRet; }
// function: ResizeData
//
// Resize Data, and move the pointer accourdingly
//
BOOL CFileModify::ResizeData(DWORD dwNewSize, LPBYTE *szString) { DWORD dwOffset = (DWORD) (DWORD_PTR) ( *szString - GetCurrentLocation() ); BOOL bRet;
bRet = ResizeData(dwNewSize);
// Move current pointer to account for possible resizing of buffer
*szString = GetCurrentLocation() + dwOffset;
return bRet; }
// function: ReadNextChunk
//
// Read in the next Chunk of Data, in order to do this, take the part of
// the chunck that has already been processed, and write it to the output
// file. Then move the rest of the chunck over, so that you can read some
// more data in. The divider between processed, and unprocessed is determined
// by the location of m_szCurrentData
//
// Data before:
// |-------------------------------------------------------------|
// | Used Data | Currently using Data | Extra Space |
// |-------------------------------------------------------------|
//
// Data after:
// |-------------------------------------------------------------|
// | Currently using Data | New Data |
// |-------------------------------------------------------------|
//
// Return:
// TRUE - The next piece of data was correctly read in
// FASLE - Their was an error, either reading from the file, or writing the
// data that we currently have to the output file.
BOOL CFileModify::ReadNextChunk() { DWORD dwUsedSize; // Size of Block used and done with (in bytes)
DWORD dwCurrentlyUsingSize; // Size of Data to keep
DWORD dwExtraSpaceSize; // Size of Free Space
DWORD dwTotalChunkSize; DWORD dwSizeofCurrentChunk;
if ( m_dwSizeofData != 0 ) { dwUsedSize = (DWORD) ( ( (BYTE*) m_szCurrentData ) - ( (BYTE*) m_buffData.QueryPtr() ) ); dwCurrentlyUsingSize = m_dwSizeofData - dwUsedSize; dwExtraSpaceSize = m_buffData.QuerySize() - dwCurrentlyUsingSize - 2; // 2 for possible LPWSTR '\0'
ASSERT( dwUsedSize <= m_dwSizeofData ); // Assert that the UsedSection is smaller that our overall section size
} else { // We have not read anything in before, so initialize stuff
dwUsedSize = 0; dwCurrentlyUsingSize = 0; dwExtraSpaceSize = m_buffData.QuerySize() - dwCurrentlyUsingSize - 2; }
if ( dwUsedSize ) { // Part of this block is done with, so lets write it to disk
dwTotalChunkSize = dwUsedSize; dwSizeofCurrentChunk = 0;
if ( m_hWriteFile != INVALID_HANDLE_VALUE ) { LPBYTE pData = (LPBYTE) m_buffData.QueryPtr();
// If we have a file open, then lets write to it, if not then we are read only
while ( dwTotalChunkSize > 0 ) { if ( ( !WriteFile(m_hWriteFile, // Handle to write file
pData, // Data to send
dwTotalChunkSize, // # of Bytes to write
&dwSizeofCurrentChunk, // Bytes Written
NULL ) ) || ( dwSizeofCurrentChunk == 0 ) ) { // We had problems writing to disk, FAIL
return FALSE; }
pData += dwSizeofCurrentChunk; dwTotalChunkSize -= dwSizeofCurrentChunk; } }
// Move Current Block
memmove( m_buffData.QueryPtr(), m_szCurrentData, dwCurrentlyUsingSize + 2 ); m_szCurrentData = ( (BYTE *) m_buffData.QueryPtr() ); m_dwSizeofData -= dwUsedSize; } else if (dwCurrentlyUsingSize) { // If there is not data to take out of the buffer, and we have data in the buffer
// Double the size of the buffer
ResizeData( m_buffData.QuerySize() * 2 ); dwExtraSpaceSize = m_buffData.QuerySize() - dwCurrentlyUsingSize - 2; // 2 for possible LPWSTR '\0'
}
if ( dwExtraSpaceSize != 0 ) { // There is space remaining in the block, so lets read the data in
dwTotalChunkSize = dwExtraSpaceSize; dwSizeofCurrentChunk = 0;
while ( dwTotalChunkSize > 0 ) { if ( !ReadFile( m_hReadFile, ( (BYTE *) m_buffData.QueryPtr() ) + dwCurrentlyUsingSize, dwTotalChunkSize, &dwSizeofCurrentChunk, NULL ) ) { // We could not read the chunk, so fail
return FALSE; }
if ( dwSizeofCurrentChunk == 0 ) { if ( dwExtraSpaceSize == dwTotalChunkSize ) { // If the extra space is the same as the totalchunksize, then we
// haven't read anything yet, so return FALSE signifying that we
// did not read anything from the file
return FALSE; }
// We are at the end of file, so break out.
break; }
dwTotalChunkSize -= dwSizeofCurrentChunk; dwCurrentlyUsingSize += dwSizeofCurrentChunk; }
// Terminate Block
m_dwSizeofData = dwCurrentlyUsingSize; SetValue(m_buffData.QueryPtr(),'\0',dwCurrentlyUsingSize / (m_bUnicode?2:1) ); }
return TRUE; }
// function: MoveCurrentPtr
//
// Move the pointer in the array
//
// Parameters
// szCurrent - New Location
//
BOOL CFileModify::MoveCurrentPtr(LPBYTE szCurrent) { if ( (szCurrent < m_buffData.QueryPtr()) || (szCurrent > ( (LPBYTE) m_buffData.QueryPtr() + m_buffData.QuerySize() ) ) ) { // This is out of range, reject position
ASSERT(FALSE); return FALSE; }
m_szCurrentData = szCurrent;
return TRUE; }
// function: GetCurrentLocation
//
// return a pointer to the current location of the pointer
LPBYTE CFileModify::GetCurrentLocation() { return m_szCurrentData; }
// function: GetBaseLocation
//
// return a pointer to the begining of the block
LPBYTE CFileModify::GetBaseLocation() { return (LPBYTE) m_buffData.QueryPtr(); }
// function: GetNextChar
// return the value of the next character
//
// Parameters:
// szCurrent - Pointer to part of our m_buffData Block
//
// Return Value:
// The unicode of ansi value for the next character
//
DWORD CFileModify::GetNextChar(LPBYTE &szCurrent) { DWORD dwValue;
if ( m_bUnicode ) { szCurrent = (LPBYTE) ( ( LPWSTR ) szCurrent) + 1; dwValue = *( ( LPWSTR ) szCurrent); } else { szCurrent = (LPBYTE) ( ( LPSTR ) szCurrent) + 1; dwValue = *( ( LPSTR ) szCurrent); }
return dwValue; }
// function: GetNextWideChar
//
// Return the value of the next wide character
//
// Return Value:
// The unicode equivalent of the next character
//
DWORD CFileModify::GetNextWideChar(LPBYTE &szCurrent) { if ( m_bUnicode ) { szCurrent = (LPBYTE) ( ( LPWSTR ) szCurrent) + 1; } else { szCurrent = (LPBYTE) CharNextA( (LPSTR) szCurrent ); }
return GetWideChar( szCurrent ); }
// function: GetPrevChar
// return the value of pointer decremeted and dereferenced
//
// Parameters:
// szCurrent - Pointer to part of our m_buffData Block
//
// Return Value:
// The unicode of ansi value for the next character that is pointer at
//
DWORD CFileModify::GetPrevChar(LPBYTE &szCurrent) { DWORD dwValue;
if ( m_bUnicode ) { szCurrent = (LPBYTE) ( ( LPWSTR ) szCurrent) - 1; dwValue = *( ( LPWSTR ) szCurrent); } else { szCurrent = (LPBYTE) ( ( LPSTR ) szCurrent) - 1; dwValue = *( ( LPSTR ) szCurrent); }
return dwValue; }
// function: GetChar
// return the value of the current character
//
// Parameters:
// szCurrent - Pointer to part of our m_buffData Block
//
// Return Value:
// The unicode of ansi value for the character that is pointer at
//
DWORD CFileModify::GetChar(LPBYTE szCurrent) { if ( m_bUnicode ) { return *( ( LPWSTR ) szCurrent ); } else { return *( ( LPSTR ) szCurrent ); } }
// function: GetWideChar
//
// Get the Wide Char equivalent of the current character
//
WCHAR CFileModify::GetWideChar(LPBYTE szCurrent) { if ( m_bUnicode ) { return (WCHAR) *( ( LPWSTR ) szCurrent ); } else { DWORD dwMBCSLen = (DWORD) ( ( (LPBYTE) CharNextA( (LPSTR) szCurrent ) ) - szCurrent ); WCHAR wChar;
if ( MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (LPSTR) szCurrent, dwMBCSLen, &wChar, sizeof(wChar)/sizeof(WCHAR) ) == 0 ) { return 0; } return wChar; } }
// function: MoveData
//
// Expand or contract data in order to add a value or remove one
//
// Parameters:
// szCurrent - A pointer to where the data will be removed/added
// iBytes - The amount of data to remove or add
//
BOOL CFileModify::MoveData(LPBYTE szCurrent, INT iBytes) { DWORD dwNewSize = ( (INT) m_dwSizeofData ) + iBytes;
if ( !ResizeData(dwNewSize, &szCurrent) ) { return FALSE; }
if ( iBytes > 0 ) { // Move bytes forward
memmove( szCurrent + iBytes, szCurrent, m_dwSizeofData - ( szCurrent - (LPBYTE) m_buffData.QueryPtr() ) + 2 ); } else if ( iBytes < 0 ) { // Move bytes back
memmove( szCurrent, szCurrent - iBytes, m_dwSizeofData - ( szCurrent - iBytes - (LPBYTE) m_buffData.QueryPtr() ) + 2 ); }
m_dwSizeofData = dwNewSize;
return TRUE; }
BOOL CFileModify::IsUnicode() { return m_bUnicode; }
// function: GetBufferSize
//
// return the size of the buffer used in this class
DWORD CFileModify::GetBufferSize() { return (m_dwSizeofData); }
// function: CXMLEdit
//
// Constructor for XMLEditor
//
CXMLEdit::CXMLEdit(): m_dwItemOffset(0), m_dwPropertyOffset(0), m_dwValueOffset(0) {
}
// function: ~CXMLEdit
//
// Destructor for XMLEditor
//
// Close Everything open
//
CXMLEdit::~CXMLEdit() { XMLFile.CloseFile(); }
// function: Open
//
// Open the file to edit
//
BOOL CXMLEdit::Open(LPTSTR szName, BOOL bModify ) { BOOL bRet;
bRet = XMLFile.OpenFile(szName,bModify);
if ( bRet ) { SetCurrentItem(XMLFile.GetCurrentLocation()); }
return bRet; }
// function: Close
//
// Close the xml file
//
BOOL CXMLEdit::Close() { return XMLFile.CloseFile(); }
// function: MoveData
//
// Move the data in the CFileModify. This also means that we need to move our
// pointers into it.
//
// Parameters:
// szCurrent - A pointer to where the data will be removed/added
// iBytes - The amount of data to remove or add
//
BOOL CXMLEdit::MoveData(LPBYTE szCurrent, INT iBytes) { return XMLFile.MoveData(szCurrent,iBytes); }
// function: ReadNextChunk();
//
// ReadNextChunk of Data
//
BOOL CXMLEdit::ReadNextChunk() { BOOL bRet; DWORD dwItemOffset = (DWORD) (DWORD_PTR) (GetCurrentItem() - XMLFile.GetCurrentLocation()); DWORD dwPropertyOffset = (DWORD) (DWORD_PTR) (GetCurrentProperty() - XMLFile.GetCurrentLocation()); DWORD dwValueOffset = (DWORD) (DWORD_PTR) (GetCurrentValue() - XMLFile.GetCurrentLocation());
bRet = XMLFile.ReadNextChunk();
// Since the CurrentLocation Pointer might have moved, move
// our pointers as well!
SetCurrentItem( ((LPBYTE) XMLFile.GetCurrentLocation()) + dwItemOffset ); SetCurrentProperty( ((LPBYTE) XMLFile.GetCurrentLocation()) + dwPropertyOffset ); SetCurrentValue( ((LPBYTE) XMLFile.GetCurrentLocation()) + dwValueOffset );
return bRet; }
// function: LoadFullItem
//
// Load the full item into memory, will all of it's properties before continuing
// The purpose of this is to make it much easier for other functions to scan
// through the buffer. It is a lot simplier, it they can assume all the information
// they need is loaded.
//
// Parameters:
// szPointerInsideBuffer [in/out] - This is a pointer to a something side of our
// file buffer. The purpose of this, is so that we can move this pointer
// so that it points to the same data before we moved the buffer
void CXMLEdit::LoadFullItem() { LPBYTE szCurrent = GetCurrentItem(); LPBYTE szCurrentTemp; DWORD cCurrent; BOOL bContinue = TRUE;
do { cCurrent = XMLFile.GetChar( szCurrent ); szCurrentTemp = szCurrent;
if ( (cCurrent == '<') || (cCurrent == '>') || ( (cCurrent == '/') && ( XMLFile.GetNextChar(szCurrentTemp) == '>' ) ) ) { // We have found the end
return; }
if ( cCurrent == '\0' ) { // We have found the end of the string, try to get the next chunk
if (!ReadNextChunk()) { return; }
// Start again at begining
szCurrent = GetCurrentItem(); } else { szCurrentTemp = szCurrent; szCurrent = SkipString(szCurrent);
if (szCurrent == szCurrentTemp) { XMLFile.GetNextChar( szCurrent ); } }
} while (bContinue);
}
// function: FindNextItem
//
// Find the next item after the pointer that we are sent
//
// Parameters:
// szStartLocation - A pointer to the current item
// bReturnName - Return a pointer to the begining of the name
//
LPBYTE CXMLEdit::FindNextItem(LPBYTE szStartLocation, BOOL bReturnName) { BOOL bQuotes; LPBYTE szCurrent; DWORD dwItemOffset;
if (!szStartLocation) { // We have no item to start at
return NULL; }
// Calculate offset for Start (incase pointer moves)
dwItemOffset = (DWORD) (DWORD_PTR) (szStartLocation - XMLFile.GetCurrentLocation());
do { // Reset szCurrent to begining of current item
szCurrent = XMLFile.GetCurrentLocation() + dwItemOffset; bQuotes = FALSE;
while ( XMLFile.GetChar( szCurrent ) != '\0') { switch ( XMLFile.GetChar( szCurrent ) ) { case '"': bQuotes = !bQuotes; break; case '<': if (!bQuotes) { LPBYTE szTempCurrent = szCurrent;
// Move past '<'
XMLFile.GetNextChar(szCurrent);
while ( IsWhiteSpace( XMLFile.GetChar( szCurrent ) ) ) { XMLFile.GetNextChar(szCurrent); }
if (bReturnName) { szTempCurrent = szCurrent; }
while ( ( XMLFile.GetChar( szCurrent ) != ' ') && ( XMLFile.GetChar( szCurrent ) != '\t') && ( XMLFile.GetChar( szCurrent ) != '\0') ) { XMLFile.GetNextChar(szCurrent); }
if ( XMLFile.GetChar( szCurrent ) != '\0') { // We could not read the whole name, because we are the end of what we
// read in, so lets try this whole thing again
return ( szTempCurrent ); }
} else { // Remove
//ASSERT(FALSE);
} break; default: break; }
if ( XMLFile.GetChar( szCurrent ) != '\0' ) { XMLFile.GetNextChar(szCurrent); } }
} while ( ReadNextChunk() );
return NULL; }
// function: FindNextItem()
//
// find the next item. This means to start at the item we are in, and get to the
// next one
//
// Parameters:
// bReturnName - Skip the '<' at the beinging of the item, and return a pointer to the
// begining of the name
LPBYTE CXMLEdit::FindNextItem(BOOL bReturnName) { return FindNextItem(GetCurrentItem(),bReturnName); }
// function: SkipString
//
// Skip over a string value, and the spaces trailing it
//
LPBYTE CXMLEdit::SkipString(LPBYTE szString, BOOL bSkipTrailingWhiteSpaces) { BOOL bQuotes = FALSE;
while ( XMLFile.GetChar( szString ) ) { switch ( XMLFile.GetChar( szString ) ) { case '"': bQuotes = !bQuotes; break; case '<': case '>': case '=': if ( !bQuotes ) { return szString; } break; default: if ( !bQuotes ) { if ( IsWhiteSpace( XMLFile.GetChar( szString ) ) ) { if (bSkipTrailingWhiteSpaces) { while ( IsWhiteSpace( XMLFile.GetChar( szString ) ) ) { XMLFile.GetNextChar(szString); } }
return szString; } } break; }
XMLFile.GetNextChar(szString); }
if (bSkipTrailingWhiteSpaces) { while ( IsWhiteSpace( XMLFile.GetChar( szString ) ) ) { XMLFile.GetNextChar(szString); } }
return szString; }
// function: FindNextProperty
//
// Find the next property in the current item
//
// Parameters:
// szCurrentValue - Pointer to Value
//
// Return Values
// NULL - Another Property was not found
// not NULL - The pointer to the next property
LPBYTE CXMLEdit::FindNextProperty(LPBYTE &szValue) { BOOL bQuotes; LPBYTE szCurrent; LPBYTE szCurrentProp; LPBYTE szCurrentValue;
if (!GetCurrentProperty()) { // We do not have a current property
return NULL; }
do { // Reset szCurrent to begining of current property
bQuotes = FALSE; szCurrent = SkipString(GetCurrentProperty());
if ( XMLFile.GetChar(szCurrent) == '=' ) { // We have found a value for our old property
XMLFile.GetNextChar(szCurrent); szCurrent = SkipString(szCurrent); }
// Set the current property
szCurrentProp = szCurrent;
// Try to find a value for this property
szCurrent = SkipString(szCurrent);
if ( XMLFile.GetChar(szCurrent) == '=' ) { // We have found a value for our new property
XMLFile.GetNextChar(szCurrent); szCurrentValue = szCurrent; } else { szCurrentValue = NULL; }
if ( ( XMLFile.GetChar(szCurrent) == '<' ) || ( XMLFile.GetChar(szCurrent) == '>' ) ) { // We have left the current item, so return NULL
return NULL; }
if ( XMLFile.GetChar(szCurrent) != '\0' ) { // We have found the next item, lets return it
szValue = szCurrentValue; return szCurrentProp; }
} while ( ReadNextChunk() );
// End of File, no more values are present.
return NULL; }
// function: MoveToNextItem
//
// Move to the Next Item
//
BOOL CXMLEdit::MovetoNextItem() { LPBYTE szTemp; LPBYTE szLastItem;
szTemp = FindNextItem(); szLastItem = GetCurrentItem(); // Do this afterwards, just incase we moved the buffer
if (szTemp == NULL) { return FALSE; }
SetCurrentItem(szTemp); SetCurrentProperty(szTemp); SetCurrentValue(szTemp);
// Always keep the last item in the buffer
// The reason for this, is because on delete we want to be able
// to back up to the '<' of the current item
XMLFile.MoveCurrentPtr(szLastItem);
return TRUE; }
// function: MoveToNextProperty
//
// Move to the Next Property
//
BOOL CXMLEdit::MovetoNextProperty() { LPBYTE szTemp; LPBYTE szTempValue = NULL;
szTemp = FindNextProperty(szTempValue);
if (szTemp == NULL) { return FALSE; }
SetCurrentProperty(szTemp);
if (szTempValue) { SetCurrentValue(szTempValue); } else { SetCurrentValue(szTemp); }
return TRUE; }
// function: MoveToFirstProperty
//
// Move to the First Property
//
BOOL CXMLEdit::MovetoFirstProperty() { SetCurrentProperty(GetCurrentItem()); SetCurrentValue(GetCurrentProperty());
return MovetoNextProperty(); }
// RetrieveCurrentValue
//
// Retrieve the current Value, and put it in pstrValue
//
BOOL CXMLEdit::RetrieveCurrentValue( TSTR *pstrValue ) { LPBYTE szBeginingofValue; LPBYTE szCurrentLocation; BOOL bInsideQuotes = FALSE; DWORD dwCurrentLen = 0; DWORD i;
LoadFullItem();
szBeginingofValue = GetCurrentValue();
if ( *szBeginingofValue == '"' ) { bInsideQuotes = TRUE; XMLFile.GetNextChar(szBeginingofValue); }
szCurrentLocation = szBeginingofValue;
while ( TRUE ) { if ( bInsideQuotes && ( XMLFile.GetWideChar(szCurrentLocation) == '"' ) ) { // Hit end
break; }
if ( ( !bInsideQuotes && IsTerminator( XMLFile.GetWideChar(szCurrentLocation) ) ) || ( XMLFile.GetWideChar(szCurrentLocation) == '\0' ) ) { // We hit the end again
break; }
XMLFile.GetNextWideChar(szCurrentLocation); dwCurrentLen++; }
if ( !pstrValue->Resize( dwCurrentLen + 1 ) ) { return FALSE; }
szCurrentLocation = szBeginingofValue;
for ( i = 0; i < dwCurrentLen; i++ ) { *(pstrValue->QueryStr() + i ) = ( WCHAR ) XMLFile.GetWideChar( szCurrentLocation ); XMLFile.GetNextWideChar( szCurrentLocation ); }
*(pstrValue->QueryStr() + i ) = '\0';
return TRUE; }
// function:IsWhiteSpace
//
// returns if the character is a space
//
BOOL CXMLEdit::IsWhiteSpace(DWORD ch) { return ( ( ch == ' ' ) || ( ch == '\t' ) || ( ch == '\r' ) || ( ch == '\n' ) ); }
// function:IsWhiteSpace
//
// returns if the character is a xml string terminator
//
BOOL CXMLEdit::IsTerminator(DWORD ch) { return ( ( ch == '\0' ) || ( ch == '=' ) || IsWhiteSpace(ch) ); }
// function: GetCurrentItem
//
// Return a pointer to the Current Item
LPBYTE CXMLEdit::GetCurrentItem() { return XMLFile.GetBaseLocation() + m_dwItemOffset; }
// function: GetCurrentProperty
//
// Return a pointer to the Current Property
LPBYTE CXMLEdit::GetCurrentProperty() { return XMLFile.GetBaseLocation() + m_dwPropertyOffset; }
// function: GetCurrentValue
//
// Return a pointer to the value for the current property
LPBYTE CXMLEdit::GetCurrentValue() { return XMLFile.GetBaseLocation() + m_dwValueOffset; }
// function: SetCurrentItem
//
// Set the location for the current item
void CXMLEdit::SetCurrentItem(LPBYTE szInput) { ASSERT( ((DWORD) ( szInput - XMLFile.GetBaseLocation() ) ) < XMLFile.GetBufferSize() );
m_dwItemOffset = (DWORD) (DWORD_PTR) (szInput - XMLFile.GetBaseLocation()); }
// function: SetCurrentProperty
//
// Set the location for the current property
void CXMLEdit::SetCurrentProperty(LPBYTE szInput) { ASSERT( ((DWORD) ( szInput - XMLFile.GetBaseLocation() ) ) < XMLFile.GetBufferSize() );
m_dwPropertyOffset = (DWORD) (DWORD_PTR) (szInput - XMLFile.GetBaseLocation()); }
// function: SetCurrentValue
//
// Set the location for the current value
void CXMLEdit::SetCurrentValue(LPBYTE szInput) { ASSERT( ((DWORD) ( szInput - XMLFile.GetBaseLocation() ) ) < XMLFile.GetBufferSize() );
m_dwValueOffset = (DWORD) (DWORD_PTR) (szInput - XMLFile.GetBaseLocation()); }
// function: FindBeginingofItem
//
// Find the begining of the current item
//
// Parameters:
// szInput - The Location to start at
//
// Return:
// NULL - Could not find the begining
// Pointer - The begining, starting with the '<'
LPBYTE CXMLEdit::FindBeginingofItem(LPBYTE szInput) { while ( ( szInput >= XMLFile.GetBaseLocation() ) && ( XMLFile.GetChar(szInput) != '\0' ) ) { if ( XMLFile.GetChar(szInput) == '<' ) { return szInput; }
XMLFile.GetPrevChar(szInput); }
return NULL; }
// function: DeleteItem()
//
// Delete an item
//
// Note: This will not only delete the current item, but it will delete any items that
// are nested inside of it.
//
// Return:
// TRUE - Deleted successfully
// FALSE - Failed to delete it
BOOL CXMLEdit::DeleteItem() { LPBYTE szBegin; LPBYTE szEnd; LPBYTE szCurrentItem; DWORD dwNestedItems = 0;
do { // Load the whole item
LoadFullItem(); // Increment this because we are inside an item
dwNestedItems++;
// Initialize to the current Item
szCurrentItem = GetCurrentItem();
// Scan for terminator
// See if this is the end of an item
if ( XMLFile.GetChar(szCurrentItem) == '/' ) { // This item is in the form </foo>, so it is the end of an item that
// was opened earlier, we have to subtract 2, one for the current item
// and one that was for the start of this one
ASSERT(dwNestedItems >= 2); dwNestedItems -= 2; }
// Move to next item
szEnd = FindNextItem(szCurrentItem,TRUE);
if (!szEnd) { // We could not find the end, so we couldn't delete it
return FALSE; }
// See if this item self terminate (ie. <FOO bar="test"/>)
while ( ( szEnd != GetCurrentItem() ) && ( XMLFile.GetPrevChar(szEnd) != '>' ) ) { // continue on
}
if ( ( XMLFile.GetChar(szEnd) == '>' ) && ( szEnd != GetCurrentItem() ) && ( XMLFile.GetPrevChar(szEnd) == '/' ) ) { // We have found an item that self terminates, so we can
// decrement the counter (ie. <foo bar="TRUE" />
ASSERT(dwNestedItems>0); dwNestedItems--; }
// Delete current item
szEnd = FindNextItem(GetCurrentItem(),FALSE);
if (!szEnd) { return FALSE; }
szBegin = FindBeginingofItem( GetCurrentItem() ); MoveData(szBegin, (DWORD) (DWORD_PTR) (szBegin - szEnd) ); szBegin = FindNextItem(szBegin,TRUE);
if (!szBegin) { return FALSE; }
SetCurrentItem(szBegin); } while ( dwNestedItems > 0 );
return TRUE; }
BOOL CXMLEdit::DeleteValue() { // Not yet implemented
ASSERT(FALSE);
return FALSE; }
BOOL CXMLEdit::DeleteProperty() { LPBYTE szTemp;
LoadFullItem();
szTemp = SkipString( GetCurrentProperty() );
if ( XMLFile.GetChar(szTemp) == '=' ) { // Skip the Value for this also
XMLFile.GetNextChar(szTemp); szTemp = SkipString(szTemp); }
if ( XMLFile.GetChar(szTemp) != '\0' ) { XMLFile.MoveData( GetCurrentProperty(), (INT) ( GetCurrentProperty() - szTemp ) ); return TRUE; }
return FALSE; }
// function: ReplaceString
//
// Replace a string at a given location, with another string
// that is passed in.
//
// Parameters:
// szLocation - The location of the variable to change
// szNewValue - The new string to replace it with
//
// Return
// TRUE - It succeeded
// FLASE - It failed
BOOL CXMLEdit::ReplaceString(LPBYTE szLocation, LPTSTR szNewValue) { LPBYTE szTemp; LPBYTE szOldCurrentItem = GetCurrentItem();
LoadFullItem();
if ( szOldCurrentItem != GetCurrentItem() ) { // Current Item has moved, so we must update the szLocation Pointer
szLocation = szLocation - (szOldCurrentItem - GetCurrentItem()); }
// Skip to the begining of the next string
szTemp = SkipString( szLocation, FALSE );
if ( XMLFile.GetChar(szTemp) != '\0' ) { MoveData( szLocation, (INT) ( _tcslen(szNewValue) - ( szTemp - szLocation ) ) ); XMLFile.CopyString( szLocation, szNewValue); return TRUE; }
return FALSE; }
// function: ReplaceItem
//
// Replace a item name at the CurrentItem()
//
// Parameters
// szNewItem - The new name item to add
//
BOOL CXMLEdit::ReplaceItem(LPTSTR szNewItem) { return ReplaceString(GetCurrentItem(),szNewItem); }
// function: ReplaceProperty
//
// Replace a property name at the property CurrentProperty()
//
// Parameters
// szProp - The new name for the property
//
BOOL CXMLEdit::ReplaceProperty(LPTSTR szNewProp) { return ReplaceString(GetCurrentProperty(),szNewProp); }
// function: ReplaceValue
//
// Replace a property name at the property CurrentProperty()
//
// Parameters
// szNewValueProp - The new name for the property
//
BOOL CXMLEdit::ReplaceValue(LPTSTR szNewValue) { if (GetCurrentProperty() == GetCurrentValue()) { // There is no value, so we will not replace the property
// by mistkae
return FALSE; }
if (*szNewValue != '"') { BUFFER buffValue;
if (buffValue.Resize((_tcslen(szNewValue) + 3) * sizeof(TCHAR))) // 3 chars = '"' + '"' + '\0'
{ // Copy the string with quotes around it.
_tcscpy((LPTSTR) buffValue.QueryPtr(), _T("\"")); _tcscat((LPTSTR) buffValue.QueryPtr(), szNewValue); _tcscat((LPTSTR) buffValue.QueryPtr(), _T("\""));
return ReplaceString(GetCurrentValue(),(LPTSTR) buffValue.QueryPtr()); }
return FALSE; } else { return ReplaceString(GetCurrentValue(),szNewValue); } }
// function: IsEqual
//
// Compares a Unicode and ANSI String to see if they are equal
//
// Note: This works on ANSI Strings, but will not work on DBCS
// Strings!
// Note: Termination character for this function is either a
// '\0', ' ', or '\t'
//
// Parameters:
// szWideString - Wide Char String
// szAnsiString - An Ansi String
//
// Return:
// TRUE - They are equal
// FALSE - They are not equal
BOOL CXMLEdit::IsEqual(LPCWSTR szWideString, LPCSTR szAnsiString) { if (*szWideString == '"') { // If the string is inside quotes, do not use that in the comparison
szWideString++; }
if (*szAnsiString == '"') { // If the string is inside quotes, do not use that in the comparison
szAnsiString++; }
while ( *szWideString && *szAnsiString && (*szWideString == *szAnsiString) ) { szWideString++; // Increment 1 character (2 bytes)
szAnsiString++; // Increment 1 character (1 byte )
}
if ( ( IsTerminator ( *szWideString ) || ( *szWideString == '"' ) ) && ( IsTerminator ( *szAnsiString ) || ( *szAnsiString == '"' ) ) ) { // We have made it throught the string, and all the
// chars were equal
return TRUE; }
return FALSE; }
// function: IsEqual
//
// Compares two unicode strings, or two ansi strings
//
// Note: This works on ANSI Strings, but will not work on DBCS
// Strings!
// Note: Termination character for this function is either a
// '\0', ' ', or '\t'
//
// Parameters:
// szString1 - String to Compare
// szString2 - String to Compare
//
// Return:
// TRUE - They are equal
// FALSE - They are not equal
BOOL CXMLEdit::IsEqual(LPCTSTR szString1, LPCTSTR szString2) { if (*szString1 == '"') { // If the string is inside quotes, do not use that in the comparison
szString1++; }
if (*szString2 == '"') { // If the string is inside quotes, do not use that in the comparison
szString2++; }
while ( *szString1 && *szString2 && (*szString1 == *szString2) ) { szString1++; // Increment 1 character (2 bytes)
szString2++; // Increment 1 character (1 byte )
}
if ( ( IsTerminator ( *szString1 ) || ( *szString1 == '"' ) ) && ( IsTerminator ( *szString2 ) || ( *szString2 == '"' ) ) ) { // We have made it throught the string, and all the
// chars were equal
return TRUE; }
return FALSE; }
// function: IsEqual
//
// Compare a LPBYTE string of type XMLFile.IsUnicode() with
// a LPTSTR
//
// Parameters:
// szGenericString - The string from our internal buffer
// szTCHARString - The string to compare with from the user
//
// Return:
// TRUE - They are the same
// FALSE - They are different
//
BOOL CXMLEdit::IsEqual(LPBYTE szGenericString, LPCTSTR szTCHARString) { if ( (!szGenericString) || (!szTCHARString) ) { // No item to compare it with
return FALSE; }
#if defined(UNICODE) || defined(_UNICODE)
// For UNICODE, szItemName is Unicode
if ( XMLFile.IsUnicode() ) { // Both are Unicode
return ( IsEqual( szTCHARString, (LPWSTR) szGenericString ) == 0 ); } else { // szGenericString is Unicode, szCurrentItem is ANSI
return ( IsEqual( szTCHARString , (LPSTR) szGenericString ) ); }
#else
// For !UNICODE, szItemName is ANSI
if ( XMLFile.IsUnicode() ) { // szGenericString is ANSI, szCurrentItem is Unicode
return ( IsEqual( (LPWSTR) szGenericString, szTCHARString ) ); } else { // Both are ANSI
return ( IsEqual( (LPSTR) szGenericString, szTCHARString ) == 0 ); }
#endif
}
// function: IsEqualItem
//
// Compares the CurrentItem Name to the one passed in
//
// Paramters:
// szItemName - The ItemName to compare with
//
BOOL CXMLEdit::IsEqualItem(LPCTSTR szItemName) { return IsEqual( GetCurrentItem(), szItemName ); }
// function: IsPropertyItem
//
// Compares the CurrentProperty Name to the one passed in
//
// Paramters:
// szItemName - The ItemName to compare with
//
BOOL CXMLEdit::IsEqualProperty(LPCTSTR szPropertyName) { return IsEqual( GetCurrentProperty(), szPropertyName ); }
// function: IsEqualValue
//
// Compares the CurrentValue to the one passed in
//
// Paramters:
// szValue - The value to coompare with
//
BOOL CXMLEdit::IsEqualValue(LPCTSTR szValue) { return IsEqual( GetCurrentValue(), szValue ); }
// function: CXML_Metabase_Upgrade::MethodName
//
LPTSTR CXML_Metabase_Upgrade::GetMethodName() { return _T("XML_Metabase_Upgrade"); }
// function: CXML_Base::ParseFile
//
// Upgrade the XML Metabase/Schema to a format that the new
// Configuration store will be happy with, and not report
// any errors to the pesky Event Log
//
// Parameters
// szFile - The file to parse
// ciList - The parameters to use, they consist of:
// 0 - The name of the Item
// 1 - Items==2 -> New name of item | Items > 2 -> Name of Property
// 2 - Items==3 -> New name of property | Items > 3 -> Value to look for
// 3 - Items==4 -> New Value | Items > 4 -> Name of Next Property to Check
// 4 - Items==5 -> New Value for last prop | Items > 5 -> Name of the Next Value to look for
// etc.
//
// Note:
// 1) A '*' as an item name, property name, or value means to replace no matter
// what it is
// 2) A '*' for a replacement character means to remove that item/property/value
// 3) A '**' for a replacement character means to remove the whole item
//
// Return Value:
// TRUE - It worked correctly
// FALSE - It failed
BOOL CXML_Base::ParseFile(LPTSTR szFile, CItemList &ciList) { CXMLEdit XMLFile; CItemList *pList; DWORD i;
// Create array of ItemLists
pList = new (CItemList[ciList.GetNumberOfItems()]);
if ( pList == NULL ) { // Could not allocation memory needed for ItemList
return FALSE; }
for (i = 0; i < ciList.GetNumberOfItems(); i++) { if ( ( !pList[i].LoadSubList( ciList.GetItem(i) ) ) || ( pList[i].GetNumberOfItems() < 2 ) ) { // Could not load one of the items
delete [] pList; return FALSE; } }
// Open the metabase, to modify it
if (!XMLFile.Open(szFile,TRUE)) { delete [] pList; return FALSE; }
while (XMLFile.MovetoNextItem()) { // Look for Item in replace list
for (i = 0; i < ciList.GetNumberOfItems(); i++) { // Is the item equal to this
if ( XMLFile.IsEqualItem( pList[i].GetItem(0) ) || ( ( *pList[i].GetItem(0) == '*' ) && ( *(pList[i].GetItem(0)+1) == '\0' ) ) ) { if ( pList[i].GetNumberOfItems() == 2 ) { // There is only 2 items, so the second item is the new name for the item, so replace/delete it
if ( ( *pList[i].GetItem(1) == '*' ) && ( *(pList[i].GetItem(1)+1) == '\0' ) ) { XMLFile.DeleteItem(); } else { XMLFile.ReplaceItem( pList[i].GetItem(1) ); } } else { // The item is found, check the properties...
XMLFile.MovetoFirstProperty();
do { if ( XMLFile.IsEqualProperty( pList[i].GetItem(1) ) || ( ( *pList[i].GetItem(1) == '*' ) && ( *(pList[i].GetItem(1)+1) == '\0' ) ) ) { // We have found a match of the property also
if ( pList[i].GetNumberOfItems() == 3 ) { // There are 3 items, so replace/delete the property name with this
if ( ( *pList[i].GetItem(2) == '*' ) && ( *(pList[i].GetItem(2)+1) == '\0' ) ) { XMLFile.DeleteProperty(); } else if ( ( *pList[i].GetItem(2) == '*' ) && ( *(pList[i].GetItem(2)+1) == '*' ) && ( *(pList[i].GetItem(2)+2) == '\0' ) ) { XMLFile.DeleteItem(); // Since we removed the item, we must jump out of the property checking
break; } else { XMLFile.ReplaceProperty( pList[i].GetItem(2) ); } } else { // Check value to make sure it is the same
if ( XMLFile.IsEqualValue( pList[i].GetItem(2) ) || ( ( *pList[i].GetItem(2) == '*' ) && ( *(pList[i].GetItem(2)+1) == '\0' ) ) ) { DWORD dwCurrentProp = 3; BOOL bContinue = TRUE;
while ( (pList[i].GetNumberOfItems() > (dwCurrentProp + 1) ) && ( bContinue ) ) { XMLFile.MovetoFirstProperty(); bContinue = FALSE; do { // compare the current property and value
if ( ( ( ( *pList[i].GetItem(dwCurrentProp) == '*' ) && ( *(pList[i].GetItem(dwCurrentProp)+1) == '\0' ) ) || // Compare Property
XMLFile.IsEqualProperty( pList[i].GetItem(dwCurrentProp) ) ) && ( ( ( *pList[i].GetItem(dwCurrentProp+1) == '*' ) && ( *(pList[i].GetItem(dwCurrentProp+1)+1) == '\0' ) ) || // Compare Value
XMLFile.IsEqualValue( pList[i].GetItem(dwCurrentProp+1) ) ) ) { // If we have found a match for both property and value, then lets continue
bContinue = TRUE; break; }
} while (XMLFile.MovetoNextProperty());
dwCurrentProp += 2; }
if (bContinue) { // The item, property, and value are correct, so replace/delete it
if ( ( *pList[i].GetItem(dwCurrentProp) == '*' ) && ( *(pList[i].GetItem(dwCurrentProp)+1) == '\0' ) ) { XMLFile.DeleteValue(); } else if ( ( *pList[i].GetItem(dwCurrentProp) == '*' ) && ( *(pList[i].GetItem(dwCurrentProp)+1) == '*' ) && ( *(pList[i].GetItem(dwCurrentProp)+2) == '\0' ) ) { XMLFile.DeleteItem(); // Since we removed the item, we must jump out of the property checking
break; } else { XMLFile.ReplaceValue( pList[i].GetItem(dwCurrentProp) ); } }
break; } } // if ( pList[i]->GetNumberofItems() == 3 )
} // if ( XMLFile.IsEqualProperty( pList[i]->GetItem(1) ) ||
} while (XMLFile.MovetoNextProperty()); } // if ( pList[i]->GetNumberofItems() == 2 )
} // if ( XMLFile.IsEqualItem( pList[i]->GetItem(0) ) ||
} // for (i = 0; i < ciList.GetNumberOfItems(); i++)
} // while (XMLFile.MovetoNextItem())
XMLFile.Close();
delete [] pList; return TRUE; }
// function: CXML_Metabase_Upgrade::DoInternalWork
//
// Upgrade the XML Metabase to a format that the new
// Configuration store will be happy with, and not report
// any errors to the pesky Event Log
//
// Return Value:
// TRUE - It worked correctly
// FALSE - It failed
//
BOOL CXML_Metabase_Upgrade::DoInternalWork(CItemList &ciList) { TSTR strMetabasePath;
if ( !GetMetabasePath( &strMetabasePath ) ) { return FALSE; }
return ParseFile( strMetabasePath.QueryStr() , ciList); }
// function: CXML_MBSchema_Upgrade::DoInternalWork
//
// Upgrade the XML MBSchema to a format that the new
// Configuration store will be happy with, and not report
// any errors to the pesky Event Log
//
// Return Value:
// TRUE - It worked correctly
// FALSE - It failed
//
BOOL CXML_MBSchema_Upgrade::DoInternalWork(CItemList &ciList) { TSTR strMBSchemaPath;
if ( !GetSchemaPath( &strMBSchemaPath ) ) { return FALSE; }
return ParseFile( strMBSchemaPath.QueryStr() , ciList); }
// function: CXML_MBSchema_Upgrade::MethodName
//
LPTSTR CXML_MBSchema_Upgrade::GetMethodName() { return _T("XML_MBSchema_Upgrade"); }
// function: GetMetabasePath
//
// Retrieve the path to the metabase
//
// Parameters
// pstrPath - [OUT] The complete path to the metabase. (assumed to be og
// _MAX_PATH size)
BOOL CXML_Base::GetMetabasePath(TSTR *pstrPath) { DWORD dwReturn;
if ( !pstrPath->Resize( MAX_PATH ) ) { return FALSE; } dwReturn = GetSystemDirectory( pstrPath->QueryStr(), pstrPath->QuerySize() );
if ( ( dwReturn == 0 ) || ( dwReturn > pstrPath->QuerySize() ) ) { // Function failed, or path was too long to append filename
return FALSE; }
if ( !pstrPath->Append( CXMLBASE_METABASEPATH ) ) { return FALSE; }
return TRUE; }
// function: GetSchemaPath
//
// Retrieve the path to the metabase schema
//
// Parameters
// pstrPath - [OUT] The complete path to the metabase. (assumed to be og
// _MAX_PATH size)
BOOL CXML_Base::GetSchemaPath(TSTR *pstrPath) { DWORD dwReturn; if ( !pstrPath->Resize( MAX_PATH ) ) { return FALSE; } dwReturn = GetSystemDirectory( pstrPath->QueryStr(), pstrPath->QuerySize() );
if ( ( dwReturn == 0 ) || ( dwReturn > pstrPath->QuerySize() ) ) { // Function failed, or path was too long to append filename
return FALSE; }
if ( !pstrPath->Append( CXMLBASE_MBSCHEMAPATH ) ) { return FALSE; }
return TRUE; }
// function: GetMethodName
//
// Return the method name for this class
LPTSTR CXML_Metabase_VerifyVersion::GetMethodName() { return ( _T("XML_Metabase_VerifyVersion") ); }
// function: GetMethodName
//
// Return the method name for this class
LPTSTR CXML_MBSchema_VerifyVersion::GetMethodName() { return ( _T("XML_MBSchema_VerifyVersion") ); }
// function: VerifyParameters:
//
// Verify that the parameters are correct fo VerifyVersion
BOOL CXML_Metabase_VerifyVersion::VerifyParameters(CItemList &ciParams) { if ( ( ciParams.GetNumberOfItems() == 2 ) && ciParams.IsNumber(0) && ciParams.IsNumber(1) ) { return TRUE; }
return FALSE; }
// function: VerifyParameters:
//
// Verify that the parameters are correct fo VerifyVersion
BOOL CXML_MBSchema_VerifyVersion::VerifyParameters(CItemList &ciParams) { if ( ( ciParams.GetNumberOfItems() == 2 ) && ciParams.IsNumber(0) && ciParams.IsNumber(1) ) { return TRUE; }
return FALSE; }
// function: IsFileWithinVersion
//
// Verify the a file is with a certain version. This is done by paring the xml of the file,
// extrapulation the verion, and making sure it is withing the bounds
//
// Parameters
// szFileName - The name of the xml file
// szItemName - The name of the item to search for
// szPropName - The name of the property that contains the version
// dwMinVer - The minimum version for it to return true
// dwMaxVer - The maximum version for it to return true
BOOL CXML_Base::IsFileWithinVersion(LPTSTR szFileName, LPTSTR szItemName, LPTSTR szPropName, DWORD dwMinVer, DWORD dwMaxVer) { CXMLEdit XMLFile; BOOL bFound = FALSE; BOOL bRet = FALSE;
if (!XMLFile.Open(szFileName, FALSE)) { return FALSE; }
while ( XMLFile.MovetoNextItem() && !bFound ) { // Look for the configuration tag
if (XMLFile.IsEqualItem( szItemName )) { XMLFile.MovetoFirstProperty();
do {
// Look for the xmlns tag that mentions the version #
if (XMLFile.IsEqualProperty( szPropName ) ) { DWORD dwVersion = XMLFile.ExtractVersion( XMLFile.GetCurrentValue() ); bFound = TRUE;
if ( ( dwMinVer >= dwMinVer ) && ( dwMaxVer <= dwMaxVer ) ) { bRet = TRUE; } }
} while ( XMLFile.MovetoNextProperty() && !bFound ); }
}
XMLFile.Close();
return bRet; }
// function: CXML_Metabase_VerifyVersion::DoInternalWork
//
// Verify the versions are within the bounds that are sent in, so we
// know wether we should execure the next command or not, by returning
// TRUE or FALSE
//
// Parameters:
// ciList -
// 0 -Minimum Bound
// 1- Max Bound
BOOL CXML_Metabase_VerifyVersion::DoInternalWork(CItemList &ciList) { TSTR strMetabasePath;
if ( !GetMetabasePath( &strMetabasePath ) ) { return FALSE; }
return IsFileWithinVersion( strMetabasePath.QueryStr(), // Filename
_T("configuration"), // Item name
_T("xmlns"), // Property Name
ciList.GetNumber(0), // Min
ciList.GetNumber(1) // Max
); }
// function: CXML_MBSchema_VerifyVersion::DoInternalWork
//
// Verify the versions are within the bounds that are sent in, so we
// know wether we should execure the next command or not, by returning
// TRUE or FALSE
//
// Parameters:
// ciList -
// 0 -Minimum Bound
// 1- Max Bound
BOOL CXML_MBSchema_VerifyVersion::DoInternalWork(CItemList &ciList) { TSTR strSchemaPath;
if ( !GetSchemaPath( &strSchemaPath ) ) { return FALSE; }
return IsFileWithinVersion( strSchemaPath.QueryStr(), // Filename
_T("MetaData"), // Item name
_T("xmlns"), // Property Name
ciList.GetNumber(0), // Min
ciList.GetNumber(1) // Max
); }
// function: ExtractVersion
//
// Extract the Version number out of a string extracted from the metabase
//
// Parameters
// szVersion - String version, such as "urn:microsoft-catalog:XML_Metabase_V1_0"
//
// RETURN
// A Verison #
DWORD CXMLEdit::ExtractVersion(LPBYTE szVersion) { DWORD dwVer = 0;
if (!szVersion) { return 0; }
while ( !IsTerminator(XMLFile.GetChar(szVersion)) ) { if ( XMLFile.GetChar(szVersion) == '_' ) { XMLFile.GetNextChar(szVersion); if ( XMLFile.GetChar(szVersion) == 'V' ) { XMLFile.GetNextChar(szVersion); break; } } else { XMLFile.GetNextChar(szVersion); } }
if (IsTerminator(XMLFile.GetChar(szVersion)) ) { return FALSE; }
while ( ( XMLFile.GetChar(szVersion) >= '0' ) && ( XMLFile.GetChar(szVersion) <= '9' ) ) { dwVer = dwVer + ( XMLFile.GetChar(szVersion) - '0' ); XMLFile.GetNextChar(szVersion); }
return dwVer; }
|