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.
2314 lines
56 KiB
2314 lines
56 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|